changeset 3464:be4ca325525a

Merge.
author Thomas Wuerthinger <thomas@wuerthinger.net>
date Wed, 27 Jul 2011 17:32:44 -0700
parents 7c4b4daac19b (diff) 9b0ca45cd756 (current diff)
children 8cd198d7cbc1 2c5b4dd06d3b a6c1f49a7319
files .hgignore .hgtags make/linux/Makefile make/linux/makefiles/cscope.make make/linux/makefiles/vm.make make/solaris/makefiles/cscope.make src/cpu/x86/vm/assembler_x86.cpp src/cpu/x86/vm/frame_x86.cpp src/cpu/x86/vm/sharedRuntime_x86_64.cpp src/os/linux/vm/os_linux.cpp src/os/windows/vm/os_windows.cpp src/share/vm/c1/c1_LIRGenerator.cpp src/share/vm/c1/c1_Runtime1.cpp src/share/vm/ci/ciCallProfile.hpp src/share/vm/ci/ciEnv.cpp src/share/vm/ci/ciEnv.hpp src/share/vm/ci/ciField.cpp src/share/vm/ci/ciObject.cpp src/share/vm/ci/ciObject.hpp src/share/vm/classfile/systemDictionary.cpp src/share/vm/classfile/systemDictionary.hpp src/share/vm/classfile/vmSymbols.hpp src/share/vm/code/codeBlob.hpp src/share/vm/code/nmethod.cpp src/share/vm/code/nmethod.hpp src/share/vm/code/pcDesc.cpp src/share/vm/compiler/compileBroker.cpp src/share/vm/compiler/oopMap.cpp src/share/vm/gc_implementation/g1/heapRegion.cpp src/share/vm/interpreter/interpreterRuntime.cpp src/share/vm/interpreter/rewriter.cpp src/share/vm/oops/instanceKlass.cpp src/share/vm/oops/klass.cpp src/share/vm/oops/methodOop.cpp src/share/vm/oops/methodOop.hpp src/share/vm/prims/jni.cpp src/share/vm/runtime/arguments.cpp src/share/vm/runtime/deoptimization.cpp src/share/vm/runtime/deoptimization.hpp src/share/vm/runtime/globals.hpp src/share/vm/runtime/javaCalls.cpp src/share/vm/runtime/sharedRuntime.cpp src/share/vm/runtime/sharedRuntime.hpp src/share/vm/runtime/thread.cpp src/share/vm/runtime/thread.hpp src/share/vm/runtime/vframeArray.cpp src/share/vm/utilities/exceptions.cpp
diffstat 794 files changed, 72856 insertions(+), 3523 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Tue Jun 28 10:57:38 2011 -0700
+++ b/.hgignore	Wed Jul 27 17:32:44 2011 -0700
@@ -1,8 +1,38 @@
 ^build/
 ^dist/
+^java/
+^java64/
+^work/
+\.metadata/
+~$
+\.csv$
+\.swp$
+\.class$
+\.log$
+\.bak$
+\.aux$
+\.pdf$
+\.dot$
+^doc/.*/dot_temp_
+^doc/doxygen/.*$
+\.orig$
+output\.txt$
+output\.cfg$
+^Test.java$
+^diff1.txt$
+^diff2.txt$
+^examples.jar$
+^graal/com.oracle.max.graal.examples/examples.jar$
+^test.xml$
+java\.hprof\.txt$
 /nbproject/private/
+^graal/hotspot/java$
+^scratch/
+scratch/
+^local/
 ^src/share/tools/hsdis/build/
 ^src/share/tools/IdealGraphVisualizer/[a-zA-Z0-9]*/build/
 ^src/share/tools/IdealGraphVisualizer/build/
 ^src/share/tools/IdealGraphVisualizer/dist/
 ^.hgtip
+^make/solaris/solaris_amd64_compiler1/
--- a/.hgtags	Tue Jun 28 10:57:38 2011 -0700
+++ b/.hgtags	Wed Jul 27 17:32:44 2011 -0700
@@ -166,6 +166,7 @@
 0930dc920c185afbf40fed9a655290b8e5b16783 hs21-b08
 611e19a16519d6fb5deea9ab565336e6e6ee475d jdk7-b139
 611e19a16519d6fb5deea9ab565336e6e6ee475d hs21-b09
+a197fd9e273c692767407654c4caf858460a413f Tested with fop, lusearch, eclipse and jtt with Xcomp flag
 d283b82966712b353fa307845a1316da42a355f4 jdk7-b140
 d283b82966712b353fa307845a1316da42a355f4 hs21-b10
 5d07913abd59261c77f24cc04a759cb75d804099 jdk7-b141
--- a/.jcheck/conf	Tue Jun 28 10:57:38 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-project=jdk7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GRAAL_AUTHORS	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,14 @@
+Lukas Stadler (stadler@ssw.jku.at)
+* July - September 2010: Initial feature-complete implementation, remote compilation
+* Since April 2011: New IR design
+
+Gilles Duboscq (gilles.duboscq@oracle.com)
+* Since April 2011: New IR design
+
+Peter Hofer (hofer@ssw.jku.at)
+* Since May 2011: Graphviz visualization
+
+Thomas Wuerthinger (thomas.wuerthinger@oracle.com)
+* June 2011: Initial prototype
+* October 2010 - January 2011: Bug fixes (all DaCapo's pass), better performance on SciMark than C1
+* Since April 2011: New IR design
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GRAAL_README	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,23 @@
+For creating a Graal VM JDK, the file jre\lib\jvm.cfg has to be modified such that it includes the line:
+-client KNOWN
+
+Before running the Graal VM, the following environment variables are needed:
+- MAXINE: Pointing to a Maxine VM repository with compiled Java files.
+- GRAAL: Pointing to a Graal VM repository with compiled Java files.
+
+In particular, the VM will look for the compiled Java files in the following directories:
+${MAXINE}/com.oracle.max.cri/bin
+${MAXINE}/com.oracle.max.base/bin
+${MAXINE}/com.oracle.max.asmdis/bin
+${MAXINE}/com.oracle.max.asm/bin
+${MAXINE}/com.oracle.max.graal.graph/bin
+${GRAAL}/graal/com.oracle.max.graal.compiler/bin
+${GRAAL}/graal/com.oracle.max.graal.runtime/bin
+${GRAAL}/graal/com.oracle.max.graal.graphviz/bin
+
+For starting the Graal VM, the two flags "-client -graal" have to be specified. Additional flags that might be useful:
+-G:Plot Sends the graphs of compiled methods via network stream to the IdealGraphVisualizer (NetBeans project at ${GRAAL}/src/share/tools/IdealGraphVisualizer that can be built and run with NetBeans 7.0, use "Graal Coloring" and "Graal Edge Coloring" filters)
+-G:Time Prints timings for the different compilation phases
+-G:Meter Prints metrics for the different compilation phases
+
+The usual HotSpot flags -Xcomp -XX:CompileOnly= -XX:CompileCommand= or -XX:+PrintCompilation can be used to control the compiled methods.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ProblemsIdeas.txt	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,85 @@
+Problems
+========
+
+* -Xcomp + synchronized method + unresolved type => deopt to bci -1
+  Example : try "runfop.sh -G:-Inline -Xcomp" should fail on the compilation of org.apache.xmlgraphics.util.Service.providers(java.lang.Class, boolean)
+  
+  The first bytecode of the method is NEW (java.lang.StringBuffer)it will deopt because java.lang.StringBuffer is not resolved, the logic in append(FixedNode) will go back until the start node, detaching the MonitorEnter from the start node and attaching the Deopt instead.
+  Deopt will now get the FrameState generated by LIRGenerator in setOperandsForLocals which is bci -1 for a synchronized method.
+
+  Can interpreter handle bci -1 for synchronized methods ? if this is the case, the corresponding assert in LIRGenerator.visitDeoptimize should be removed as bci -1 should now only be used for synchronized entry points and not for exception handling or anything else
+
+
+* Deopt caused by profiling can interfer with later optimisations
+  Exmple : have a look to some of the visit methods in avrora.arch.legacy.LegacyInterpreter sometimes if constructs which are used to materialize some booleans have a Deopt branch which prevents us from detecting an opportunity for a MaterilizeNode canonicalization. As long as the MaterializeNode itself doesnt get canonicalized away and in the end translates to jumps in the final assembly this doesnt really matter but it may if we optimise the emitted assembly
+
+Ideas
+=====
+
+* Always inline 'specialization' methods
+  Example :
+  public void foo(int a) {
+      foo(a, 1); // invoke 1
+  }
+
+  public void foo(int a, int b) {
+      foo(a, b, false); // invoke 2
+  }
+
+  public void foo(int a, int b, boolean c) {
+      // ...
+  }
+ 
+  Here invoke 1 and 2 should always be inlined regardless of the size of the inlined graph/method size and without increasing the inlining depth
+  specializations should always be inlined if we are in a trivial method, not only he methods with only one invoke, we shoudl also do it for exemple for methods that invoke and only do simple operations on paramteres or result
+
+
+* 'computable' slots in Framstates/debug info
+
+  Framestates/debug info will keep some values live for longer than they should because the values are needed for exemple for a very unlikely Deopt, this increases the pressure on register allocator.
+  In the current system Deopt is the unlikely/slow path so maybe we can make it a bit slower to avoid this problem and increase fast path performances.
+  An idea would be to insert an 'expression' in some slots instead of value referances, the expression would use values that have to be live at this point for program semantics reasons.
+  Expressions would then be evaluated by the runtime when the framestate values are needed. Expression operators probably have to be kept simple (non-trapping arithmetics)
+  This could be done by deopting to some deopt handler that will fixup the computable slots, this would probably require less runtime hacking. For exemple an object containing the informations necessary to fixup the framestate could be inserted in one of the framestate solts and then used by a deopt handler called in the same way than the deopt handler example.
+
+
+* Profilable expressions
+
+  Some optimizations may benefit from knowing is some assumption can be done. For exemple some loop optimisations may want to know the likelyhood of 2 values being aliased so that it can know if inserting a deopt-if-aliased guard is really beneficial.
+  This kind of information can not always be derived just from branch probabilities and it would be interesting to be able to ask the runtime to profile an expression, the simplest version would be to generate a boolean expression and get the probability for it being true.
+  This requires going through the compiler and asking for further profiling there are 2 main options here :
+   - Reprofile the method in interpreter with the new profiled expression (we may modify the method bytecode to insert a conditional branch on the expression we want to profile, thus using the classical branch probability infrastructure)
+   - insert a profiling snippet in the compiled code and ask runtime to recompile the method after N executions
+
+
+* Transform some contiguous array accesses into phis when possible
+  Example : (most probably found in scientific code, for example relaxation code)
+  
+  for (int i = 1; i < A.length - 1; i++) {
+     vm1 = A[i-1];
+     v0  = A[i];
+     vp1 = A[i+1];
+     // ...
+  }
+
+  should be transformed into
+  vm1 = A[0];
+  v0 = A[1];
+  for (int i = 0; i < A.length - 1; i++) {
+     vp1 = A[i+1];
+     // ...
+     vm1 = v0;
+     v0 = vp1;
+  }
+
+  This could be done in the context of a more advanced induction varaible analysis to be able to detect such access patterns. In this example we removed 2 array access (2 loads + 2 address computation + 2 bounds checks if not hoisted) while only adding 2 moves (phis)
+
+
+* Implement array bounds check elimination
+
+* Rematerialize only the nodes that were affected by GVN
+  This will probably require something that tracks changes to the Graph, the cost of such a tracking should be evaluated
+
+* Hints on register pressure
+
+  Sometimes we can make better decisions if we know the register pressure, it would be nice to have a way to know about it. Maybe we have register allocation on SSA we can somehow interact with it and try to lower the pressure in some areas on request?
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/clean	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,5 @@
+#!/bin/bash
+pushd make
+LANG=C ARCH_DATA_MODEL=64 HOTSPOT_BUILD_JOBS=16 make clean
+popd
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/create64.cmd	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,12 @@
+set HotSpotMksHome=C:\cygwin\bin
+set JAVA_HOME=%cd%\java64
+set ORIG_PATH=%PATH%
+set path=%JAVA_HOME%\bin;%path%;C:\cygwin\bin
+
+set OrigPath=%cd%
+cd make\windows
+call create.bat %OrigPath%
+
+set PATH=%ORIG_PATH%
+cd %OrigPath%
+pause
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/create_examples.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<project default="create_run_jar" name="Create Runnable Jar for Project com.oracle.max.graal.examples">
+    <!--this file was created by Eclipse Runnable JAR Export Wizard-->
+    <!--ANT 1.7 is required                                        -->
+    <target name="create_run_jar">
+        <jar destfile="./examples.jar" filesetmanifest="mergewithoutmain">
+            <manifest>
+                <attribute name="Main-Class" value="com.oracle.max.graal.examples.Main"/>
+                <attribute name="Class-Path" value="."/>
+            </manifest>
+            <fileset dir="./graal/com.oracle.max.graal.examples/bin"/>
+        </jar>
+    </target>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/domake	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,56 @@
+#!/bin/bash
+
+test -n "$JDK7" || { echo "Need to set JDK7 environment variable to the base of a JDK 1.7"; exit 1; }
+test -n "$JDK7G" || { echo "Need to set JDK7G environment variable to the base of a JDK 1.7"; exit 1; }
+
+# Resolve location of this script
+me="${BASH_SOURCE[0]}"
+while [ -h "$me" ]; do
+    me=`readlink -e "$me"`
+done
+graal_home=$(cd `dirname $me`; pwd)
+
+grep '-client KNOWN' $JDK7/jre/lib/amd64/jvm.cfg >/dev/null
+if [ $? -ne 0 ] ; then
+    echo "The setting for -client in $JDK7/jre/lib/amd64/jvm.cfg must be:"
+    echo
+    echo "  -client KNOWN"
+    echo
+    exit 1
+fi
+
+grep '-client KNOWN' $JDK7G/jre/lib/amd64/jvm.cfg >/dev/null
+if [ $? -ne 0 ] ; then
+    echo "The setting for -client in $JDK7G/jre/lib/amd64/jvm.cfg must be:"
+    echo
+    echo "  -client KNOWN"
+    echo
+    exit 1
+fi
+
+java_link="$graal_home/graal/hotspot/java"
+if [ ! -e $java_link ]; then
+    echo "Creating link: $java_link -> $JDK7/jre/bin/java"
+    ln -s $JDK7/jre/bin/java $java_link
+fi
+
+client_dir=$JDK7/jre/lib/amd64/client
+if [ ! -e $client_dir ]; then
+    echo "Creating client compiler dir: $client_dir"
+    mkdir $client_dir
+fi
+
+client_dir=$JDK7G/jre/lib/amd64/client
+if [ ! -e $client_dir ]; then
+    echo "Creating debug client compiler dir: $client_dir"
+    mkdir $client_dir
+fi
+
+pushd $graal_home/make
+
+# the piping magic runs stderr through grep and removes the complaints about Xusage.txt files
+ARCH_DATA_MODEL=64 LANG=C HOTSPOT_BUILD_JOBS=4 ALT_BOOTDIR=$JDK7G INSTALL=y make jvmg1 3>&1 1>&2 2>&3 | grep -v Xusage[.]txt
+ARCH_DATA_MODEL=64 LANG=C HOTSPOT_BUILD_JOBS=4 ALT_BOOTDIR=$JDK7 INSTALL=y make product1 3>&1 1>&2 2>&3 | grep -v Xusage[.]txt
+
+popd
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doxygen.sh	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+if [ -z "${MAXINE}" ]; then
+  echo "MAXINE is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${GRAAL}" ]; then
+  echo "GRAAL is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+
+# Resolve location of this script
+me="${BASH_SOURCE[0]}"
+while [ -h "$me" ]; do
+    me=`readlink -e "$me"`
+done
+script_home=$(cd `dirname $me`; pwd)/doc/doxygen
+
+echo "script home: $script_home"
+echo "removing temp dirs"
+
+rm -r $script_home/src
+rm -r $script_home/html
+rm -r $script_home/latex
+
+echo "collecting sources"
+mkdir -p $script_home/src
+cp -r $GRAAL/graal/GraalCompiler/src/* $script_home/src/
+cp -r $GRAAL/graal/GraalGraph/src/* $script_home/src/
+cp -r $MAXINE/CRI/src/* $script_home/src/
+
+echo "preparing sources"
+find $script_home/src/ -type f -print0 | xargs -0 sed -i 's/{@code \([^}]*\)}/\1/g'
+find $script_home/src/ -type f -print0 | xargs -0 sed -i 's/{@code/ /g'
+
+pushd $script_home
+echo "running doxygen"
+doxygen ../graal.doxy > out.txt 2> err.txt
+cat err.txt | grep -v "unable to resolve link" | grep -v "expected whitespace" | grep -v ACCESSOR | grep -v "not documented" > errors.txt
+rm err.txt
+popd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/.checkstyle	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<fileset-config file-format-version="1.2.0" simple-config="true">
+    <local-check-config name="C1X Checkstyle checks" location=".checkstyle_checks.xml" type="project" description="">
+        <additional-data name="protect-config-file" value="false"/>
+    </local-check-config>
+    <fileset name="all" enabled="true" check-config-name="C1X Checkstyle checks" local="true">
+        <file-match-pattern match-pattern="." include-pattern="true"/>
+    </fileset>
+</fileset-config>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/.checkstyle_checks.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,191 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN" "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
+
+<!--
+    This configuration file was written by the eclipse-cs plugin configuration editor
+-->
+<!--
+    Checkstyle-Configuration: C1X Checkstyle checks
+    Description: none
+-->
+<module name="Checker">
+  <property name="severity" value="warning"/>
+  <module name="TreeWalker">
+    <property name="tabWidth" value="4"/>
+    <module name="FileContentsHolder"/>
+    <module name="JavadocStyle">
+      <property name="checkHtml" value="false"/>
+    </module>
+    <module name="LocalFinalVariableName"/>
+    <module name="LocalVariableName"/>
+    <module name="MemberName">
+      <property name="format" value="^(([a-z][a-zA-Z0-9]*$)|(_[A-Z][a-zA-Z0-9]*_[a-z][a-zA-Z0-9]*$))"/>
+    </module>
+    <module name="MethodName">
+      <property name="format" value="^[a-z][a-z_A-Z0-9]*$"/>
+    </module>
+    <module name="PackageName"/>
+    <module name="ParameterName"/>
+    <module name="TypeName">
+      <property name="format" value="^[A-Z][_a-zA-Z0-9]*$"/>
+    </module>
+    <module name="RedundantImport"/>
+    <module name="LineLength">
+      <property name="max" value="250"/>
+    </module>
+    <module name="MethodParamPad"/>
+    <module name="NoWhitespaceAfter">
+      <property name="tokens" value="ARRAY_INIT,BNOT,DEC,DOT,INC,LNOT,UNARY_MINUS,UNARY_PLUS"/>
+    </module>
+    <module name="NoWhitespaceBefore">
+      <property name="tokens" value="SEMI,DOT,POST_DEC,POST_INC"/>
+    </module>
+    <module name="ParenPad"/>
+    <module name="TypecastParenPad">
+      <property name="tokens" value="RPAREN,TYPECAST"/>
+    </module>
+    <module name="WhitespaceAfter"/>
+    <module name="WhitespaceAround">
+      <property name="tokens" value="ASSIGN,BAND,BAND_ASSIGN,BOR,BOR_ASSIGN,BSR,BSR_ASSIGN,BXOR,BXOR_ASSIGN,COLON,DIV,DIV_ASSIGN,EQUAL,GE,GT,LAND,LE,LITERAL_ASSERT,LITERAL_CATCH,LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_FOR,LITERAL_IF,LITERAL_RETURN,LITERAL_SYNCHRONIZED,LITERAL_TRY,LITERAL_WHILE,LOR,LT,MINUS,MINUS_ASSIGN,MOD,MOD_ASSIGN,NOT_EQUAL,PLUS,PLUS_ASSIGN,QUESTION,SL,SLIST,SL_ASSIGN,SR,SR_ASSIGN,STAR,STAR_ASSIGN,LITERAL_ASSERT,TYPE_EXTENSION_AND"/>
+    </module>
+    <module name="RedundantModifier"/>
+    <module name="AvoidNestedBlocks">
+      <property name="allowInSwitchCase" value="true"/>
+    </module>
+    <module name="EmptyBlock">
+      <property name="option" value="text"/>
+      <property name="tokens" value="LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_IF,LITERAL_TRY,LITERAL_WHILE,STATIC_INIT"/>
+    </module>
+    <module name="LeftCurly"/>
+    <module name="NeedBraces"/>
+    <module name="RightCurly"/>
+    <module name="DoubleCheckedLocking">
+      <property name="severity" value="error"/>
+    </module>
+    <module name="EmptyStatement"/>
+    <module name="HiddenField">
+      <property name="severity" value="ignore"/>
+      <property name="ignoreConstructorParameter" value="true"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="FinalClass"/>
+    <module name="HideUtilityClassConstructor">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="ArrayTypeStyle"/>
+    <module name="UpperEll"/>
+    <module name="FallThrough"/>
+    <module name="FinalLocalVariable">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="MultipleVariableDeclarations"/>
+    <module name="StringLiteralEquality">
+      <property name="severity" value="error"/>
+    </module>
+    <module name="SuperFinalize"/>
+    <module name="UnnecessaryParentheses">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="Indentation">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="StaticVariableName">
+      <property name="format" value="^[A-Za-z][a-zA-Z0-9]*$"/>
+    </module>
+    <module name="EmptyForInitializerPad"/>
+    <module name="EmptyForIteratorPad"/>
+    <module name="ModifierOrder"/>
+    <module name="DefaultComesLast"/>
+    <module name="InnerAssignment">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="JUnitTestCase"/>
+    <module name="ModifiedControlVariable"/>
+    <module name="MutableException"/>
+    <module name="ParameterAssignment">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="RegexpSinglelineJava">
+      <property name="format" value="\s$"/>
+      <property name="message" value="Illegal trailing whitespace(s) at the end of the line."/>
+      <property name="ignoreComments" value="true"/>
+      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Checks for trailing spaces at the end of a line"/>
+    </module>
+    <module name="RegexpSinglelineJava">
+      <property name="format" value=" ,"/>
+      <property name="ignoreComments" value="true"/>
+      <metadata name="com.atlassw.tools.eclipse.checkstyle.customMessage" value="Illegal whitespace before a comma."/>
+      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Checks for whitespace before a comma."/>
+    </module>
+  </module>
+  <module name="RegexpHeader">
+    <property name="header" value="/\*\n \* Copyright \(c\) (20[0-9][0-9], )?20[0-9][0-9], Oracle and/or its affiliates. All rights reserved.\n \* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n \*\n \* This code is free software; you can redistribute it and/or modify it\n \* under the terms of the GNU General Public License version 2 only, as\n \* published by the Free Software Foundation.\n \*\n \* This code is distributed in the hope that it will be useful, but WITHOUT\n \* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n \* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n \* version 2 for more details \(a copy is included in the LICENSE file that\n \* accompanied this code\).\n \*\n \* You should have received a copy of the GNU General Public License version\n \* 2 along with this work; if not, write to the Free Software Foundation,\n \* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n \*\n \* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n \* or visit www.oracle.com if you need additional information or have any\n \* questions.\n \*/\n"/>
+  </module>
+  <module name="FileTabCharacter">
+    <property name="severity" value="error"/>
+  </module>
+  <module name="NewlineAtEndOfFile">
+    <property name="lineSeparator" value="lf"/>
+  </module>
+  <module name="Translation"/>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="Checkstyle: stop constant name check"/>
+    <property name="onCommentFormat" value="Checkstyle: resume constant name check"/>
+    <property name="checkFormat" value="ConstantNameCheck"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Allow non-conforming constant names"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="Checkstyle: stop method name check"/>
+    <property name="onCommentFormat" value="Checkstyle: resume method name check"/>
+    <property name="checkFormat" value="MethodName"/>
+    <property name="checkC" value="false"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable method name checks"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="CheckStyle: stop parameter assignment check"/>
+    <property name="onCommentFormat" value="CheckStyle: resume parameter assignment check"/>
+    <property name="checkFormat" value="ParameterAssignment"/>
+    <property name="checkC" value="false"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable Parameter Assignment"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="Checkstyle: stop final variable check"/>
+    <property name="onCommentFormat" value="Checkstyle: resume final variable check"/>
+    <property name="checkFormat" value="FinalLocalVariable"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable final variable checks"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="Checkstyle: stop"/>
+    <property name="onCommentFormat" value="Checkstyle: resume"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable all checks"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="// START GENERATED RAW ASSEMBLER METHODS"/>
+    <property name="onCommentFormat" value="// END GENERATED RAW ASSEMBLER METHODS"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable all checks for generated raw assembler methods"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="// START GENERATED LABEL ASSEMBLER METHODS"/>
+    <property name="onCommentFormat" value="// END GENERATED LABEL ASSEMBLER METHODS"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable all checks for generated label assembler methods"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="CheckStyle: stop inner assignment check"/>
+    <property name="onCommentFormat" value="CheckStyle: resume inner assignment check"/>
+    <property name="checkFormat" value="InnerAssignment"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable inner assignment checks"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="Checkstyle: stop field name check"/>
+    <property name="onCommentFormat" value="Checkstyle: resume field name check"/>
+    <property name="checkFormat" value="MemberName"/>
+    <property name="checkC" value="false"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable field name checks"/>
+  </module>
+</module>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/.classpath	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.asm"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.cri"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.graal.graphviz"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.graal.graph"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/.project	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>com.oracle.max.graal.compiler</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>net.sourceforge.metrics.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>net.sf.eclipsecs.core.CheckstyleBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>net.sourceforge.metrics.nature</nature>
+		<nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
+	</natures>
+</projectDescription>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/.settings/JavaSourceCodeFormatting.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,264 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<profiles version="11">
+<profile kind="CodeFormatterProfile" name="C1XJavaCodeStyle" version="11">
+<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="4"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
+<setting id="org.eclipse.jdt.core.compiler.source" value="1.5"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="200"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="8"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
+<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
+<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
+<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.5"/>
+<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="4"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="120"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.5"/>
+<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
+</profile>
+</profiles>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/.settings/org.eclipse.jdt.core.prefs	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,355 @@
+#Tue Jul 13 10:33:43 PDT 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.codeComplete.argumentPrefixes=
+org.eclipse.jdt.core.codeComplete.argumentSuffixes=
+org.eclipse.jdt.core.codeComplete.fieldPrefixes=
+org.eclipse.jdt.core.codeComplete.fieldSuffixes=
+org.eclipse.jdt.core.codeComplete.localPrefixes=
+org.eclipse.jdt.core.codeComplete.localSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=ignore
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=error
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=disabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+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.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=ignore
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=1
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert
+org.eclipse.jdt.core.formatter.comment.line_length=120
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=4
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=4
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
+org.eclipse.jdt.core.formatter.indentation.size=8
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=true
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=200
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=true
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=true
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=space
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=true
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=false
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/.settings/org.eclipse.jdt.ui.prefs	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,64 @@
+#Thu Feb 18 11:36:17 PST 2010
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_MaxineJavaCodeStyle
+formatter_settings_version=11
+org.eclipse.jdt.ui.exception.name=e
+org.eclipse.jdt.ui.gettersetter.use.is=true
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=java;javax;org;com;
+org.eclipse.jdt.ui.keywordthis=false
+org.eclipse.jdt.ui.ondemandthreshold=0
+org.eclipse.jdt.ui.overrideannotation=true
+org.eclipse.jdt.ui.staticondemandthreshold=0
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=false
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=false
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.make_local_variable_final=false
+sp_cleanup.make_parameters_final=false
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=false
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=false
+sp_cleanup.remove_unnecessary_nls_tags=false
+sp_cleanup.remove_unused_imports=false
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=false
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=false
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/LICENSE	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,347 @@
+The GNU General Public License (GPL)
+
+Version 2, June 1991
+
+Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Everyone is permitted to copy and distribute verbatim copies of this license
+document, but changing it is not allowed.
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to share
+and change it.  By contrast, the GNU General Public License is intended to
+guarantee your freedom to share and change free software--to make sure the
+software is free for all its users.  This General Public License applies to
+most of the Free Software Foundation's software and to any other program whose
+authors commit to using it.  (Some other Free Software Foundation software is
+covered by the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+When we speak of free software, we are referring to freedom, not price.  Our
+General Public Licenses are designed to make sure that you have the freedom to
+distribute copies of free software (and charge for this service if you wish),
+that you receive source code or can get it if you want it, that you can change
+the software or use pieces of it in new free programs; and that you know you
+can do these things.
+
+To protect your rights, we need to make restrictions that forbid anyone to deny
+you these rights or to ask you to surrender the rights.  These restrictions
+translate to certain responsibilities for you if you distribute copies of the
+software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis or for
+a fee, you must give the recipients all the rights that you have.  You must
+make sure that they, too, receive or can get the source code.  And you must
+show them these terms so they know their rights.
+
+We protect your rights with two steps: (1) copyright the software, and (2)
+offer you this license which gives you legal permission to copy, distribute
+and/or modify the software.
+
+Also, for each author's protection and ours, we want to make certain that
+everyone understands that there is no warranty for this free software.  If the
+software is modified by someone else and passed on, we want its recipients to
+know that what they have is not the original, so that any problems introduced
+by others will not reflect on the original authors' reputations.
+
+Finally, any free program is threatened constantly by software patents.  We
+wish to avoid the danger that redistributors of a free program will
+individually obtain patent licenses, in effect making the program proprietary.
+To prevent this, we have made it clear that any patent must be licensed for
+everyone's free use or not licensed at all.
+
+The precise terms and conditions for copying, distribution and modification
+follow.
+
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+0. This License applies to any program or other work which contains a notice
+placed by the copyright holder saying it may be distributed under the terms of
+this General Public License.  The "Program", below, refers to any such program
+or work, and a "work based on the Program" means either the Program or any
+derivative work under copyright law: that is to say, a work containing the
+Program or a portion of it, either verbatim or with modifications and/or
+translated into another language.  (Hereinafter, translation is included
+without limitation in the term "modification".) Each licensee is addressed as
+"you".
+
+Activities other than copying, distribution and modification are not covered by
+this License; they are outside its scope.  The act of running the Program is
+not restricted, and the output from the Program is covered only if its contents
+constitute a work based on the Program (independent of having been made by
+running the Program).  Whether that is true depends on what the Program does.
+
+1. You may copy and distribute verbatim copies of the Program's source code as
+you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this License
+and to the absence of any warranty; and give any other recipients of the
+Program a copy of this License along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and you may
+at your option offer warranty protection in exchange for a fee.
+
+2. You may modify your copy or copies of the Program or any portion of it, thus
+forming a work based on the Program, and copy and distribute such modifications
+or work under the terms of Section 1 above, provided that you also meet all of
+these conditions:
+
+    a) You must cause the modified files to carry prominent notices stating
+    that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in whole or
+    in part contains or is derived from the Program or any part thereof, to be
+    licensed as a whole at no charge to all third parties under the terms of
+    this License.
+
+    c) If the modified program normally reads commands interactively when run,
+    you must cause it, when started running for such interactive use in the
+    most ordinary way, to print or display an announcement including an
+    appropriate copyright notice and a notice that there is no warranty (or
+    else, saying that you provide a warranty) and that users may redistribute
+    the program under these conditions, and telling the user how to view a copy
+    of this License.  (Exception: if the Program itself is interactive but does
+    not normally print such an announcement, your work based on the Program is
+    not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If identifiable
+sections of that work are not derived from the Program, and can be reasonably
+considered independent and separate works in themselves, then this License, and
+its terms, do not apply to those sections when you distribute them as separate
+works.  But when you distribute the same sections as part of a whole which is a
+work based on the Program, the distribution of the whole must be on the terms
+of this License, whose permissions for other licensees extend to the entire
+whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your
+rights to work written entirely by you; rather, the intent is to exercise the
+right to control the distribution of derivative or collective works based on
+the Program.
+
+In addition, mere aggregation of another work not based on the Program with the
+Program (or with a work based on the Program) on a volume of a storage or
+distribution medium does not bring the other work under the scope of this
+License.
+
+3. You may copy and distribute the Program (or a work based on it, under
+Section 2) in object code or executable form under the terms of Sections 1 and
+2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable source
+    code, which must be distributed under the terms of Sections 1 and 2 above
+    on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three years, to
+    give any third party, for a charge no more than your cost of physically
+    performing source distribution, a complete machine-readable copy of the
+    corresponding source code, to be distributed under the terms of Sections 1
+    and 2 above on a medium customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer to
+    distribute corresponding source code.  (This alternative is allowed only
+    for noncommercial distribution and only if you received the program in
+    object code or executable form with such an offer, in accord with
+    Subsection b above.)
+
+The source code for a work means the preferred form of the work for making
+modifications to it.  For an executable work, complete source code means all
+the source code for all modules it contains, plus any associated interface
+definition files, plus the scripts used to control compilation and installation
+of the executable.  However, as a special exception, the source code
+distributed need not include anything that is normally distributed (in either
+source or binary form) with the major components (compiler, kernel, and so on)
+of the operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the source
+code from the same place counts as distribution of the source code, even though
+third parties are not compelled to copy the source along with the object code.
+
+4. You may not copy, modify, sublicense, or distribute the Program except as
+expressly provided under this License.  Any attempt otherwise to copy, modify,
+sublicense or distribute the Program is void, and will automatically terminate
+your rights under this License.  However, parties who have received copies, or
+rights, from you under this License will not have their licenses terminated so
+long as such parties remain in full compliance.
+
+5. You are not required to accept this License, since you have not signed it.
+However, nothing else grants you permission to modify or distribute the Program
+or its derivative works.  These actions are prohibited by law if you do not
+accept this License.  Therefore, by modifying or distributing the Program (or
+any work based on the Program), you indicate your acceptance of this License to
+do so, and all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+6. Each time you redistribute the Program (or any work based on the Program),
+the recipient automatically receives a license from the original licensor to
+copy, distribute or modify the Program subject to these terms and conditions.
+You may not impose any further restrictions on the recipients' exercise of the
+rights granted herein.  You are not responsible for enforcing compliance by
+third parties to this License.
+
+7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues), conditions
+are imposed on you (whether by court order, agreement or otherwise) that
+contradict the conditions of this License, they do not excuse you from the
+conditions of this License.  If you cannot distribute so as to satisfy
+simultaneously your obligations under this License and any other pertinent
+obligations, then as a consequence you may not distribute the Program at all.
+For example, if a patent license would not permit royalty-free redistribution
+of the Program by all those who receive copies directly or indirectly through
+you, then the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply and
+the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or
+other property right claims or to contest validity of any such claims; this
+section has the sole purpose of protecting the integrity of the free software
+distribution system, which is implemented by public license practices.  Many
+people have made generous contributions to the wide range of software
+distributed through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing to
+distribute software through any other system and a licensee cannot impose that
+choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+8. If the distribution and/or use of the Program is restricted in certain
+countries either by patents or by copyrighted interfaces, the original
+copyright holder who places the Program under this License may add an explicit
+geographical distribution limitation excluding those countries, so that
+distribution is permitted only in or among countries not thus excluded.  In
+such case, this License incorporates the limitation as if written in the body
+of this License.
+
+9. The Free Software Foundation may publish revised and/or new versions of the
+General Public License from time to time.  Such new versions will be similar in
+spirit to the present version, but may differ in detail to address new problems
+or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any later
+version", you have the option of following the terms and conditions either of
+that version or of any later version published by the Free Software Foundation.
+If the Program does not specify a version number of this License, you may
+choose any version ever published by the Free Software Foundation.
+
+10. If you wish to incorporate parts of the Program into other free programs
+whose distribution conditions are different, write to the author to ask for
+permission.  For software which is copyrighted by the Free Software Foundation,
+write to the Free Software Foundation; we sometimes make exceptions for this.
+Our decision will be guided by the two goals of preserving the free status of
+all derivatives of our free software and of promoting the sharing and reuse of
+software generally.
+
+NO WARRANTY
+
+11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
+THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN OTHERWISE
+STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE
+PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND
+PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE,
+YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL
+ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE
+PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
+INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
+BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER
+OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+END OF TERMS AND CONDITIONS
+
+How to Apply These Terms to Your New Programs
+
+If you develop a new program, and you want it to be of the greatest possible
+use to the public, the best way to achieve this is to make it free software
+which everyone can redistribute and change under these terms.
+
+To do so, attach the following notices to the program.  It is safest to attach
+them to the start of each source file to most effectively convey the exclusion
+of warranty; and each file should have at least the "copyright" line and a
+pointer to where the full notice is found.
+
+    One line to give the program's name and a brief idea of what it does.
+
+    Copyright (C) <year> <name of author>
+
+    This program is free software; you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by the Free
+    Software Foundation; either version 2 of the License, or (at your option)
+    any later version.
+
+    This program is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc., 59
+    Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this when it
+starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author Gnomovision comes
+    with ABSOLUTELY NO WARRANTY; for details type 'show w'.  This is free
+    software, and you are welcome to redistribute it under certain conditions;
+    type 'show c' for details.
+
+The hypothetical commands 'show w' and 'show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may be
+called something other than 'show w' and 'show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.  Here
+is a sample; alter the names:
+
+    Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+    'Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+    signature of Ty Coon, 1 April 1989
+
+    Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General Public
+License instead of this License.
+
+
+"CLASSPATH" EXCEPTION TO THE GPL
+
+Certain source files distributed by Sun Microsystems, Inc.  are subject to
+the following clarification and special exception to the GPL, but only where
+Sun has expressly included in the particular source file's header the words
+"Sun designates this particular file as subject to the "Classpath" exception
+as provided by Sun in the LICENSE file that accompanied this code."
+
+    Linking this library statically or dynamically with other modules is making
+    a combined work based on this library.  Thus, the terms and conditions of
+    the GNU General Public License cover the whole combination.
+
+    As a special exception, the copyright holders of this library give you
+    permission to link this library with independent modules to produce an
+    executable, regardless of the license terms of these independent modules,
+    and to copy and distribute the resulting executable under terms of your
+    choice, provided that you also meet, for each linked independent module,
+    the terms and conditions of the license of that module.  An independent
+    module is a module which is not derived from or based on this library.  If
+    you modify this library, you may extend this exception to your version of
+    the library, but you are not obligated to do so.  If you do not wish to do
+    so, delete this exception statement from your version.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompilation.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.max.graal.compiler;
+
+import java.util.*;
+
+import com.oracle.max.asm.*;
+import com.oracle.max.graal.compiler.alloc.*;
+import com.oracle.max.graal.compiler.asm.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.compiler.gen.LIRGenerator.DeoptimizationStub;
+import com.oracle.max.graal.compiler.graph.*;
+import com.oracle.max.graal.compiler.lir.*;
+import com.oracle.max.graal.compiler.observer.*;
+import com.oracle.max.graal.compiler.value.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * This class encapsulates global information about the compilation of a particular method,
+ * including a reference to the runtime, statistics about the compiled code, etc.
+ */
+public final class GraalCompilation {
+
+    private static ThreadLocal<GraalCompilation> currentCompilation = new ThreadLocal<GraalCompilation>();
+
+    public final GraalCompiler compiler;
+    public final CiTarget target;
+    public final RiRuntime runtime;
+    public final RiMethod method;
+    public final RiRegisterConfig registerConfig;
+    public final CiStatistics stats;
+    public final FrameState placeholderState;
+
+    public final CompilerGraph graph;
+
+    private boolean hasExceptionHandlers;
+    private final GraalCompilation parent;
+
+    /**
+     * @see #setNotTypesafe()
+     * @see #isTypesafe()
+     */
+    private boolean typesafe = true;
+
+    private int nextID = 1;
+
+    private FrameMap frameMap;
+    private TargetMethodAssembler assembler;
+
+    private IR hir;
+
+    private LIRGenerator lirGenerator;
+
+    /**
+     * Creates a new compilation for the specified method and runtime.
+     *
+     * @param compiler the compiler
+     * @param method the method to be compiled or {@code null} if generating code for a stub
+     * @param osrBCI the bytecode index for on-stack replacement, if requested
+     * @param stats externally supplied statistics object to be used if not {@code null}
+     */
+    public GraalCompilation(GraalCompiler compiler, RiMethod method, int osrBCI, CiStatistics stats) {
+        if (osrBCI != -1) {
+            throw new CiBailout("No OSR supported");
+        }
+        this.parent = currentCompilation.get();
+        currentCompilation.set(this);
+        this.compiler = compiler;
+        this.target = compiler.target;
+        this.runtime = compiler.runtime;
+        this.graph = new CompilerGraph(runtime);
+        this.method = method;
+        this.stats = stats == null ? new CiStatistics() : stats;
+        this.registerConfig = method == null ? compiler.globalStubRegisterConfig : runtime.getRegisterConfig(method);
+        this.placeholderState = method != null && method.minimalDebugInfo() ? new FrameState(method, 0, 0, 0, 0, false, graph) : null;
+
+        if (compiler.isObserved()) {
+            compiler.fireCompilationStarted(new CompilationEvent(this));
+        }
+    }
+
+    public void close() {
+        currentCompilation.set(parent);
+    }
+
+    public IR hir() {
+        return hir;
+    }
+
+    /**
+     * Records that this compilation has exception handlers.
+     */
+    public void setHasExceptionHandlers() {
+        hasExceptionHandlers = true;
+    }
+
+    /**
+     * Translates a given kind to a canonical architecture kind.
+     * This is an identity function for all but {@link CiKind#Word}
+     * which is translated to {@link CiKind#Int} or {@link CiKind#Long}
+     * depending on whether or not this is a {@linkplain #is64Bit() 64-bit}
+     * compilation.
+     */
+    public CiKind archKind(CiKind kind) {
+        if (kind.isWord()) {
+            return target.arch.is64bit() ? CiKind.Long : CiKind.Int;
+        }
+        return kind;
+    }
+
+    /**
+     * Determines if two given kinds are equal at the {@linkplain #archKind(CiKind) architecture} level.
+     */
+    public boolean archKindsEqual(CiKind kind1, CiKind kind2) {
+        return archKind(kind1) == archKind(kind2);
+    }
+
+    /**
+     * Converts this compilation to a string.
+     *
+     * @return a string representation of this compilation
+     */
+    @Override
+    public String toString() {
+        return "compile: " + method;
+    }
+
+    /**
+     * Builds the block map for the specified method.
+     *
+     * @param method the method for which to build the block map
+     * @param osrBCI the OSR bytecode index; {@code -1} if this is not an OSR
+     * @return the block map for the specified method
+     */
+    public BlockMap getBlockMap(RiMethod method) {
+        BlockMap map = new BlockMap(method);
+        map.build();
+        if (compiler.isObserved()) {
+            String label = CiUtil.format("BlockListBuilder %f %r %H.%n(%p)", method, true);
+            compiler.fireCompilationEvent(new CompilationEvent(this, label, map, method.codeSize()));
+        }
+        stats.bytecodeCount += method.code().length;
+        return map;
+    }
+
+    /**
+     * Returns the frame map of this compilation.
+     * @return the frame map
+     */
+    public FrameMap frameMap() {
+        return frameMap;
+    }
+
+    public TargetMethodAssembler assembler() {
+        if (assembler == null) {
+            AbstractAssembler asm = compiler.backend.newAssembler(registerConfig);
+            assembler = new TargetMethodAssembler(asm);
+            assembler.setFrameSize(frameMap.frameSize());
+            assembler.targetMethod.setCustomStackAreaOffset(frameMap.offsetToCustomArea());
+        }
+        return assembler;
+    }
+
+    public boolean hasExceptionHandlers() {
+        return hasExceptionHandlers;
+    }
+
+    public CiResult compile() {
+        CiTargetMethod targetMethod;
+        try {
+            emitHIR();
+            emitLIR();
+            targetMethod = emitCode();
+
+            if (GraalOptions.Meter) {
+                GraalMetrics.BytecodesCompiled += method.codeSize();
+            }
+        } catch (CiBailout b) {
+            return new CiResult(null, b, stats);
+        } catch (Throwable t) {
+            if (GraalOptions.BailoutOnException) {
+                return new CiResult(null, new CiBailout("Exception while compiling: " + method, t), stats);
+            } else {
+                if (t instanceof RuntimeException) {
+                    throw (RuntimeException) t;
+                } else {
+                    throw new RuntimeException("Exception while compiling: " + method, t);
+                }
+            }
+        } finally {
+            if (compiler.isObserved()) {
+                compiler.fireCompilationFinished(new CompilationEvent(this));
+            }
+        }
+
+        return new CiResult(targetMethod, null, stats);
+    }
+
+    public IR emitHIR() {
+        hir = new IR(this);
+        hir.build();
+        return hir;
+    }
+
+    public void initFrameMap(int numberOfLocks) {
+        frameMap = this.compiler.backend.newFrameMap(method, numberOfLocks);
+    }
+
+    private void emitLIR() {
+        if (GraalOptions.GenLIR) {
+            if (GraalOptions.Time) {
+                GraalTimers.LIR_CREATE.start();
+            }
+
+            initFrameMap(hir.maxLocks());
+
+            lirGenerator = compiler.backend.newLIRGenerator(this);
+
+            for (LIRBlock b : hir.linearScanOrder()) {
+                lirGenerator.doBlock(b);
+            }
+
+            if (GraalOptions.Time) {
+                GraalTimers.LIR_CREATE.stop();
+            }
+
+            if (GraalOptions.PrintLIR && !TTY.isSuppressed()) {
+                LIRList.printLIR(hir.linearScanOrder());
+            }
+
+            new LinearScan(this, hir, lirGenerator, frameMap()).allocate();
+        }
+    }
+
+    private CiTargetMethod emitCode() {
+        if (GraalOptions.GenLIR && GraalOptions.GenCode) {
+            final LIRAssembler lirAssembler = compiler.backend.newLIRAssembler(this);
+            lirAssembler.emitCode(hir.codeEmittingOrder());
+
+            // generate code for slow cases
+            lirAssembler.emitLocalStubs();
+
+            // generate deoptimization stubs
+            ArrayList<DeoptimizationStub> deoptimizationStubs = lirGenerator.deoptimizationStubs();
+            if (deoptimizationStubs != null) {
+                for (DeoptimizationStub stub : deoptimizationStubs) {
+                    lirAssembler.emitDeoptizationStub(stub);
+                }
+            }
+
+            // generate traps at the end of the method
+            lirAssembler.emitTraps();
+
+            CiTargetMethod targetMethod = assembler().finishTargetMethod(method, runtime, lirAssembler.registerRestoreEpilogueOffset, false);
+            if (graph.assumptions().count() > 0) {
+                targetMethod.setAssumptions(graph.assumptions());
+            }
+
+            if (compiler.isObserved()) {
+                compiler.fireCompilationEvent(new CompilationEvent(this, "After code generation", graph, false, true, targetMethod));
+            }
+
+            if (GraalOptions.Time) {
+                GraalTimers.CODE_CREATE.stop();
+            }
+            return targetMethod;
+        }
+
+        return null;
+    }
+
+    public int nextID() {
+        return nextID++;
+    }
+
+    public static GraalCompilation compilation() {
+        GraalCompilation compilation = currentCompilation.get();
+        assert compilation != null;
+        return compilation;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompiler.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.globalstub.*;
+import com.oracle.max.graal.compiler.observer.*;
+import com.oracle.max.graal.compiler.target.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+import com.sun.cri.xir.*;
+
+public class GraalCompiler extends ObservableCompiler {
+
+    public final Map<Object, GlobalStub> stubs = new HashMap<Object, GlobalStub>();
+
+    /**
+     * The target that this compiler has been configured for.
+     */
+    public final CiTarget target;
+
+    /**
+     * The runtime that this compiler has been configured for.
+     */
+    public final RiRuntime runtime;
+
+    /**
+     * The XIR generator that lowers Java operations to machine operations.
+     */
+    public final RiXirGenerator xir;
+
+    /**
+     * The backend that this compiler has been configured for.
+     */
+    public final Backend backend;
+
+    public final RiRegisterConfig globalStubRegisterConfig;
+
+    private GraalCompilation currentCompilation;
+
+    public GraalCompiler(RiRuntime runtime, CiTarget target, RiXirGenerator xirGen, RiRegisterConfig globalStubRegisterConfig) {
+        this.runtime = runtime;
+        this.target = target;
+        this.xir = xirGen;
+        this.globalStubRegisterConfig = globalStubRegisterConfig;
+        this.backend = Backend.create(target.arch, this);
+        init();
+
+        Graph.verificationListeners.add(new VerificationListener() {
+            @Override
+            public void verificationFailed(Node n, String message) {
+                GraalCompiler.this.fireCompilationEvent(new CompilationEvent(currentCompilation, "Verification Error on Node " + n.id(), currentCompilation.graph, true, false, true));
+                TTY.println(n.toString());
+                for (Node p : n.predecessors()) {
+                    TTY.println("predecessor: " + p);
+                }
+                for (Node p : n.usages()) {
+                    TTY.println("usage: " + p);
+                }
+                assert false : "Verification of node " + n + " failed: " + message;
+            }
+        });
+    }
+
+    public CiResult compileMethod(RiMethod method, int osrBCI, RiXirGenerator xirGenerator, CiStatistics stats) {
+        GraalTimers.TOTAL.start();
+        long startTime = 0;
+        int index = GraalMetrics.CompiledMethods++;
+        if (GraalOptions.PrintCompilation) {
+            TTY.print(String.format("Graal %4d %-70s %-45s | ", index, method.holder().name(), method.name()));
+            startTime = System.nanoTime();
+        }
+
+        CiResult result = null;
+        TTY.Filter filter = new TTY.Filter(GraalOptions.PrintFilter, method);
+        GraalCompilation compilation = new GraalCompilation(this, method, osrBCI, stats);
+        currentCompilation = compilation;
+        try {
+            result = compilation.compile();
+        } finally {
+            filter.remove();
+            compilation.close();
+            if (GraalOptions.PrintCompilation && !TTY.isSuppressed()) {
+                long time = (System.nanoTime() - startTime) / 100000;
+                TTY.println(String.format("%3d.%dms", time / 10, time % 10));
+            }
+            GraalTimers.TOTAL.stop();
+        }
+
+        return result;
+    }
+
+    private void init() {
+        final List<XirTemplate> xirTemplateStubs = xir.buildTemplates(backend.newXirAssembler());
+        final GlobalStubEmitter emitter = backend.newGlobalStubEmitter();
+
+        if (xirTemplateStubs != null) {
+            for (XirTemplate template : xirTemplateStubs) {
+                TTY.Filter filter = new TTY.Filter(GraalOptions.PrintFilter, template.name);
+                try {
+                    stubs.put(template, emitter.emit(template, runtime));
+                } finally {
+                    filter.remove();
+                }
+            }
+        }
+
+        for (GlobalStub.Id id : GlobalStub.Id.values()) {
+            TTY.Filter suppressor = new TTY.Filter(GraalOptions.PrintFilter, id);
+            try {
+                stubs.put(id, emitter.emit(id, runtime));
+            } finally {
+                suppressor.remove();
+            }
+        }
+
+        if (GraalOptions.PrintCFGToFile) {
+            addCompilationObserver(new CFGPrinterObserver());
+        }
+        if (GraalOptions.PrintDOTGraphToFile) {
+            addCompilationObserver(new GraphvizPrinterObserver(false));
+        }
+        if (GraalOptions.PrintDOTGraphToPdf) {
+            addCompilationObserver(new GraphvizPrinterObserver(true));
+        }
+        if (GraalOptions.PrintIdealGraphLevel != 0 || GraalOptions.Plot || GraalOptions.PlotOnError) {
+            CompilationObserver observer;
+            if (GraalOptions.PrintIdealGraphFile) {
+                observer = new IdealGraphPrinterObserver();
+            } else {
+                observer = new IdealGraphPrinterObserver(GraalOptions.PrintIdealGraphAddress, GraalOptions.PrintIdealGraphPort);
+            }
+            addCompilationObserver(observer);
+        }
+    }
+
+    public GlobalStub lookupGlobalStub(GlobalStub.Id id) {
+        GlobalStub globalStub = stubs.get(id);
+        assert globalStub != null : "no stub for global stub id: " + id;
+        return globalStub;
+    }
+
+    public GlobalStub lookupGlobalStub(XirTemplate template) {
+        GlobalStub globalStub = stubs.get(template);
+        assert globalStub != null : "no stub for XirTemplate: " + template;
+        return globalStub;
+    }
+
+    public GlobalStub lookupGlobalStub(CiRuntimeCall runtimeCall) {
+        GlobalStub globalStub = stubs.get(runtimeCall);
+        if (globalStub == null) {
+            globalStub = backend.newGlobalStubEmitter().emit(runtimeCall, runtime);
+            stubs.put(runtimeCall, globalStub);
+        }
+
+        assert globalStub != null : "could not find global stub for runtime call: " + runtimeCall;
+        return globalStub;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalMetrics.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler;
+
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.Map.*;
+
+import com.oracle.max.graal.compiler.debug.*;
+
+
+/**
+ * This class contains a number of fields that collect metrics about compilation, particularly
+ * the number of times certain optimizations are performed.
+ */
+public final class GraalMetrics {
+    public static int CompiledMethods;
+    public static int TargetMethods;
+    public static int LocalValueNumberHits;
+    public static int ValueMapResizes;
+    public static int InlinedFinalizerChecks;
+    public static int InlineForcedMethods;
+    public static int InlineForbiddenMethods;
+    public static int BlocksDeleted;
+    public static int BytecodesCompiled;
+    public static int CodeBytesEmitted;
+    public static int SafepointsEmitted;
+    public static int ExceptionHandlersEmitted;
+    public static int DataPatches;
+    public static int DirectCallSitesEmitted;
+    public static int IndirectCallSitesEmitted;
+    public static int LiveHIRInstructions;
+    public static int LIRInstructions;
+    public static int LIRVariables;
+    public static int LIRXIRInstructions;
+    public static int LIRMoveInstructions;
+    public static int LSRAIntervalsCreated;
+    public static int LSRASpills;
+    public static int LoadConstantIterations;
+    public static int CodeBufferCopies;
+    public static int UniqueValueIdsAssigned;
+    public static int FrameStatesCreated;
+    public static int FrameStateValuesCreated;
+    public static int NodesCanonicalized;
+    public static int LoopsPeeled;
+    public static int LoopsInverted;
+    public static int PartialUsageProbability;
+    public static int FullUsageProbability;
+    public static int Rematerializations;
+    public static int GlobalValueNumberingHits;
+
+    public static void print() {
+        for (Entry<String, GraalMetrics> m : map.entrySet()) {
+            printField(m.getKey(), m.getValue().value);
+        }
+        printClassFields(GraalMetrics.class);
+    }
+
+    private static LinkedHashMap<String, GraalMetrics> map = new LinkedHashMap<String, GraalMetrics>();
+
+    public static GraalMetrics get(String name) {
+        if (!map.containsKey(name)) {
+            map.put(name, new GraalMetrics(name));
+        }
+        return map.get(name);
+    }
+
+    private GraalMetrics(String name) {
+        this.name = name;
+    }
+
+    private int value;
+    private String name;
+
+    public void increment() {
+        increment(1);
+    }
+
+    public void increment(int val) {
+        value += val;
+    }
+
+    public static void printClassFields(Class<?> javaClass) {
+        final String className = javaClass.getSimpleName();
+        TTY.println(className + " {");
+        for (final Field field : javaClass.getFields()) {
+            printField(field, false);
+        }
+        TTY.println("}");
+    }
+
+    public static void printField(final Field field, boolean tabbed) {
+        final String fieldName = String.format("%35s", field.getName());
+        try {
+            String prefix = tabbed ? "" : "    " + fieldName + " = ";
+            String postfix = tabbed ? "\t" : "\n";
+            if (field.getType() == int.class) {
+                TTY.print(prefix + field.getInt(null) + postfix);
+            } else if (field.getType() == boolean.class) {
+                TTY.print(prefix + field.getBoolean(null) + postfix);
+            } else if (field.getType() == float.class) {
+                TTY.print(prefix + field.getFloat(null) + postfix);
+            } else if (field.getType() == String.class) {
+                TTY.print(prefix + field.get(null) + postfix);
+            } else if (field.getType() == Map.class) {
+                Map<?, ?> m = (Map<?, ?>) field.get(null);
+                TTY.print(prefix + printMap(m) + postfix);
+            } else {
+                TTY.print(prefix + field.get(null) + postfix);
+            }
+        } catch (IllegalAccessException e) {
+            // do nothing.
+        }
+    }
+
+    private static String printMap(Map<?, ?> m) {
+        StringBuilder sb = new StringBuilder();
+
+        List<String> keys = new ArrayList<String>();
+        for (Object key : m.keySet()) {
+            keys.add((String) key);
+        }
+        Collections.sort(keys);
+
+        for (String key : keys) {
+            sb.append(key);
+            sb.append("\t");
+            sb.append(m.get(key));
+            sb.append("\n");
+        }
+
+        return sb.toString();
+    }
+
+    private static void printField(String fieldName, long value) {
+        TTY.print("    " + fieldName + " = " + value + "\n");
+    }
+
+    private static void printField(String fieldName, double value) {
+        TTY.print("    " + fieldName + " = " + value + "\n");
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler;
+
+import com.oracle.max.graal.compiler.debug.TTY.*;
+
+/**
+ * This class encapsulates options that control the behavior of the Graal compiler.
+ * The help message for each option is specified by a {@linkplain #helpMap help map}.
+ *
+ * (tw) WARNING: Fields of this class are treated as final by Graal.
+ */
+public final class GraalOptions {
+
+    // Checkstyle: stop
+    private static final boolean ____ = false;
+    // Checkstyle: resume
+
+    public static boolean Lower                              = true;
+
+    // inlining settings
+    public static boolean Inline                             = true;
+    public static boolean Intrinsify                         = true;
+    public static boolean CacheGraphs                        = ____;
+    public static boolean InlineWithTypeCheck                = ____;
+    public static int     MaximumInstructionCount            = 3000;
+    public static float   MaximumInlineRatio                 = 0.90f;
+    public static int     MaximumInlineSize                  = 35;
+    public static int     MaximumFreqInlineSize              = 200;
+    public static int     FreqInlineRatio                    = 20;
+    public static int     MaximumTrivialSize                 = 6;
+    public static int     MaximumInlineLevel                 = 9;
+    public static int     MaximumRecursiveInlineLevel        = 2;
+    public static int     MaximumDesiredSize                 = 8000;
+    public static int     MaximumShortLoopSize               = 5;
+
+    // escape analysis settings
+    public static boolean EscapeAnalysis                     = ____;
+    public static int     ForcedInlineEscapeWeight           = 100;
+    public static int     MaximumEscapeAnalysisArrayLength   = 32;
+    public static boolean PrintEscapeAnalysis                = ____;
+
+    // absolute probability analysis
+    public static boolean ProbabilityAnalysis                = true;
+
+    //rematerialize settings
+    public static double  MinimumUsageProbability            = 0.95;
+
+    // debugging settings
+    public static boolean VerifyPointerMaps                  = ____;
+    public static int     MethodEndBreakpointGuards          = 0;
+    public static boolean ZapStackOnMethodEntry              = ____;
+    public static boolean StressLinearScan                   = ____;
+    public static boolean BailoutOnException                 = ____;
+    public static boolean DeoptALot                          = ____;
+    public static boolean Verify                             = true;
+    public static boolean TestGraphDuplication               = ____;
+
+    /**
+     * See {@link Filter#Filter(String, Object)}.
+     */
+    public static String  PrintFilter                        = null;
+
+    // printing settings
+    public static boolean PrintLIR                           = ____;
+    public static boolean PrintCFGToFile                     = ____;
+
+    // DOT output settings
+    public static boolean PrintDOTGraphToFile                = ____;
+    public static boolean PrintDOTGraphToPdf                 = ____;
+    public static boolean OmitDOTFrameStates                 = ____;
+
+    public static boolean Extend                             = ____;
+
+    // Ideal graph visualizer output settings
+    public static boolean Plot                               = ____;
+    public static boolean PlotVerbose                        = ____;
+    public static boolean PlotOnError                        = ____;
+    public static int     PrintIdealGraphLevel               = 0;
+    public static boolean PrintIdealGraphFile                = ____;
+    public static String  PrintIdealGraphAddress             = "127.0.0.1";
+    public static int     PrintIdealGraphPort                = 4444;
+
+    // Other printing settings
+    public static boolean Meter                              = ____;
+    public static boolean Time                               = ____;
+    public static boolean PrintCompilation                   = ____;
+    public static boolean PrintXirTemplates                  = ____;
+    public static boolean PrintIRWithLIR                     = ____;
+    public static boolean PrintAssembly                      = ____;
+    public static boolean PrintCodeBytes                     = ____;
+    public static int     PrintAssemblyBytesPerLine          = 16;
+    public static int     TraceLinearScanLevel               = 0;
+    public static int     TraceLIRGeneratorLevel             = 0;
+    public static boolean TraceRelocation                    = ____;
+    public static boolean TraceLIRVisit                      = ____;
+    public static boolean TraceAssembler                     = ____;
+    public static boolean TraceInlining                      = ____;
+    public static boolean TraceDeadCodeElimination           = ____;
+    public static boolean TraceEscapeAnalysis                = ____;
+    public static boolean TraceCanonicalizer                 = ____;
+    public static boolean TraceMemoryMaps                    = ____;
+    public static boolean TraceProbability                 = ____;
+    public static boolean TraceReadElimination               = ____;
+    public static boolean TraceGVN                           = ____;
+    public static int     TraceBytecodeParserLevel           = 0;
+    public static boolean QuietBailout                       = ____;
+
+    // state merging settings
+    public static boolean AssumeVerifiedBytecode             = ____;
+
+    // Linear scan settings
+    public static boolean CopyPointerStackArguments          = true;
+
+    // Code generator settings
+    public static boolean GenLIR                             = true;
+    public static boolean GenCode                            = true;
+    public static boolean UseBranchPrediction                = true;
+    public static boolean UseExceptionProbability            = ____;
+    public static int     MatureInvocationCount              = 100;
+    public static boolean GenSafepoints                      = true;
+
+    public static boolean UseConstDirectCall                 = ____;
+
+    public static boolean GenSpecialDivChecks                = ____;
+    public static boolean GenAssertionCode                   = ____;
+    public static boolean AlignCallsForPatching              = true;
+    public static boolean NullCheckUniquePc                  = ____;
+    public static boolean InvokeSnippetAfterArguments        = ____;
+    public static boolean ResolveClassBeforeStaticInvoke     = true;
+
+    // Translating tableswitch instructions
+    public static int     SequentialSwitchLimit              = 4;
+    public static int     RangeTestsSwitchDensity            = 5;
+
+    public static boolean DetailedAsserts                    = ____;
+
+    // Runtime settings
+    public static int     ReadPrefetchInstr                  = 0;
+    public static int     StackShadowPages                   = 2;
+
+    // Assembler settings
+    public static boolean CommentedAssembly                  = ____;
+    public static boolean PrintLIRWithAssembly               = ____;
+
+    public static boolean OptReadElimination                 = ____;
+    public static boolean OptGVN                             = ____;
+    public static boolean Rematerialize                      = ____;
+    public static boolean OptCanonicalizer                   = true;
+    public static boolean OptLoops                           = ____;
+    public static boolean OptOptimisticSchedule              = ____;
+    public static boolean OptReorderLoops                    = ____;
+    public static boolean LoopPeeling                        = ____;
+    public static boolean LoopInversion                      = ____;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalTimers.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2009, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler;
+
+import java.util.*;
+import java.util.Map.*;
+
+import com.oracle.max.graal.compiler.debug.*;
+
+/**
+ * This class contains timers that record the amount of time spent in various
+ * parts of the compiler.
+ */
+public final class GraalTimers {
+    private static LinkedHashMap<String, GraalTimers> map = new LinkedHashMap<String, GraalTimers>();
+
+
+    public static final GraalTimers TOTAL = get("Total compilation time");
+    public static final GraalTimers COMPUTE_LINEAR_SCAN_ORDER = get("Compute Linear Scan Order");
+    public static final GraalTimers LIR_CREATE = get("Create LIR");
+    public static final GraalTimers LIFETIME_ANALYSIS = get("Lifetime Analysis");
+    public static final GraalTimers LINEAR_SCAN = get("Linear Scan");
+    public static final GraalTimers RESOLUTION = get("Resolution");
+    public static final GraalTimers DEBUG_INFO = get("Create Debug Info");
+    public static final GraalTimers CODE_CREATE = get("Create Code");
+
+    private final String name;
+    private long start;
+    private long total;
+
+    private GraalTimers(String name) {
+        this.name = name;
+    }
+
+
+    public static GraalTimers get(String name) {
+        if (!map.containsKey(name)) {
+            map.put(name, new GraalTimers(name));
+        }
+        return map.get(name);
+    }
+
+    public void start() {
+        start = System.nanoTime();
+    }
+
+    public void stop() {
+        total += System.nanoTime() - start;
+    }
+
+    public static void reset() {
+        for (Entry<String, GraalTimers> e : map.entrySet()) {
+            e.getValue().total = 0;
+        }
+    }
+
+    public static void print() {
+
+        TTY.println();
+        TTY.println("%-30s: %7.4f s", TOTAL.name, TOTAL.total / 1000000000.0);
+        for (Entry<String, GraalTimers> e : map.entrySet()) {
+            GraalTimers timer = e.getValue();
+            if (timer != TOTAL) {
+                TTY.println("%-30s: %7.4f s (%5.2f%%)", timer.name, timer.total / 1000000000.0, timer.total * 100.0 / TOTAL.total);
+                timer.total = 0;
+            }
+        }
+        TTY.println();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ControlFlowOptimizer.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.alloc;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.graph.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.lir.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.sun.cri.ci.*;
+
+/**
+ * This class performs basic optimizations on the control flow graph after LIR generation.
+ */
+final class ControlFlowOptimizer {
+
+    /**
+     * Performs control flow optimizations on the given IR graph.
+     * @param ir the IR graph that should be optimized
+     */
+    public static void optimize(IR ir) {
+        ControlFlowOptimizer optimizer = new ControlFlowOptimizer(ir);
+        List<LIRBlock> code = ir.codeEmittingOrder();
+        optimizer.reorderShortLoops(code);
+        optimizer.deleteEmptyBlocks(code);
+        optimizer.deleteUnnecessaryJumps(code);
+        optimizer.deleteJumpsToReturn(code);
+    }
+
+    private final IR ir;
+
+    private ControlFlowOptimizer(IR ir) {
+        this.ir = ir;
+    }
+
+    private void reorderShortLoop(List<LIRBlock> code, LIRBlock headerBlock, int headerIdx) {
+        int i = headerIdx + 1;
+        int maxEnd = Math.min(headerIdx + GraalOptions.MaximumShortLoopSize, code.size());
+        while (i < maxEnd && code.get(i).loopDepth() >= headerBlock.loopDepth()) {
+            i++;
+        }
+
+        if (i == code.size() || code.get(i).loopDepth() < headerBlock.loopDepth()) {
+            int endIdx = i - 1;
+            LIRBlock endBlock = code.get(endIdx);
+
+            if (endBlock.numberOfSux() == 1 && endBlock.suxAt(0) == headerBlock) {
+                // short loop from headerIdx to endIdx found . reorder blocks such that
+                // the headerBlock is the last block instead of the first block of the loop
+
+                for (int j = headerIdx; j < endIdx; j++) {
+                    code.set(j, code.get(j + 1));
+                }
+                code.set(endIdx, headerBlock);
+            }
+        }
+    }
+
+    private void reorderShortLoops(List<LIRBlock> code) {
+        for (int i = code.size() - 1; i >= 0; i--) {
+            LIRBlock block = code.get(i);
+
+            if (block.isLinearScanLoopHeader()) {
+                reorderShortLoop(code, block, i);
+            }
+        }
+
+        assert verify(code);
+    }
+
+    // only blocks with exactly one successor can be deleted. Such blocks
+    // must always end with an unconditional branch to this successor
+    private boolean canDeleteBlock(LIRBlock block) {
+        if (block.numberOfSux() != 1 ||
+            block == ir.startBlock ||
+            block.suxAt(0) == block) {
+            return false;
+        }
+
+        List<LIRInstruction> instructions = block.lir().instructionsList();
+
+        assert instructions.size() >= 2 : "block must have label and branch";
+        assert instructions.get(0).code == LIROpcode.Label : "first instruction must always be a label";
+        assert instructions.get(instructions.size() - 1) instanceof LIRBranch : "last instruction must always be a branch but is " + instructions.get(instructions.size() - 1);
+        assert ((LIRBranch) instructions.get(instructions.size() - 1)).cond() == Condition.TRUE : "branch must be unconditional";
+        assert ((LIRBranch) instructions.get(instructions.size() - 1)).block() == block.suxAt(0) : "branch target must be the successor " + ((LIRBranch) instructions.get(instructions.size() - 1)).block();
+
+        // block must have exactly one successor
+
+        return instructions.size() == 2 && instructions.get(instructions.size() - 1).info == null;
+    }
+
+    private void deleteEmptyBlocks(List<LIRBlock> code) {
+        int oldPos = 0;
+        int newPos = 0;
+        int numBlocks = code.size();
+
+        while (oldPos < numBlocks) {
+            LIRBlock block = code.get(oldPos);
+
+            if (canDeleteBlock(block)) {
+                LIRBlock newTarget = block.suxAt(0);
+
+                // update the block references in any branching LIR instructions
+                for (LIRBlock pred : block.blockPredecessors()) {
+                    for (LIRInstruction instr : pred.lir().instructionsList()) {
+                        if (instr instanceof LIRBranch) {
+                            ((LIRBranch) instr).substitute(block, newTarget);
+                        } else if (instr instanceof LIRTableSwitch) {
+                            ((LIRTableSwitch) instr).substitute(block, newTarget);
+                        } else if (instr instanceof LIRXirInstruction) {
+                            ((LIRXirInstruction) instr).substitute(block, newTarget);
+                        }
+                    }
+                }
+
+                // adjust successor and predecessor lists
+                block.replaceWith(newTarget);
+                GraalMetrics.BlocksDeleted++;
+            } else {
+                // adjust position of this block in the block list if blocks before
+                // have been deleted
+                if (newPos != oldPos) {
+                    code.set(newPos, code.get(oldPos));
+                }
+                newPos++;
+            }
+            oldPos++;
+        }
+        assert verify(code);
+        Util.truncate(code, newPos);
+
+        assert verify(code);
+    }
+
+    private void deleteUnnecessaryJumps(List<LIRBlock> code) {
+        // skip the last block because there a branch is always necessary
+        for (int i = code.size() - 2; i >= 0; i--) {
+            LIRBlock block = code.get(i);
+            List<LIRInstruction> instructions = block.lir().instructionsList();
+
+            LIRInstruction lastOp = instructions.get(instructions.size() - 1);
+            if (lastOp.code == LIROpcode.Branch) {
+                assert lastOp instanceof LIRBranch : "branch must be of type LIRBranch";
+                LIRBranch lastBranch = (LIRBranch) lastOp;
+
+                if (lastBranch.block() == null) {
+                    // this might target a deoptimization stub...
+                    // TODO check if the target is really a deopt stub...
+//                    assert lastBranch.block() != null : "last branch must always have a block as target, current block #" + block.blockID();
+                    continue;
+                }
+                assert lastBranch.label() == lastBranch.block().label() : "must be equal";
+
+                if (lastBranch.info == null) {
+                    if (lastBranch.block() == code.get(i + 1)) {
+                        // delete last branch instruction
+                        Util.truncate(instructions, instructions.size() - 1);
+
+                    } else {
+                        LIRInstruction prevOp = instructions.get(instructions.size() - 2);
+                        if (prevOp.code == LIROpcode.Branch || prevOp.code == LIROpcode.CondFloatBranch) {
+                            assert prevOp instanceof LIRBranch : "branch must be of type LIRBranch";
+                            LIRBranch prevBranch = (LIRBranch) prevOp;
+
+                            if (prevBranch.block() == code.get(i + 1) && prevBranch.info == null) {
+                                // eliminate a conditional branch to the immediate successor
+                                prevBranch.changeBlock(lastBranch.block());
+                                prevBranch.negateCondition();
+                                Util.truncate(instructions, instructions.size() - 1);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        assert verify(code);
+    }
+
+    private void deleteJumpsToReturn(List<LIRBlock> code) {
+        for (int i = code.size() - 1; i >= 0; i--) {
+            LIRBlock block = code.get(i);
+            List<LIRInstruction> curInstructions = block.lir().instructionsList();
+            LIRInstruction curLastOp = curInstructions.get(curInstructions.size() - 1);
+
+            assert curInstructions.get(0).code == LIROpcode.Label : "first instruction must always be a label";
+            if (curInstructions.size() == 2 && curLastOp.code == LIROpcode.Return) {
+                // the block contains only a label and a return
+                // if a predecessor ends with an unconditional jump to this block, then the jump
+                // can be replaced with a return instruction
+                //
+                // Note: the original block with only a return statement cannot be deleted completely
+                // because the predecessors might have other (conditional) jumps to this block.
+                // this may lead to unnecesary return instructions in the final code
+
+                assert curLastOp.info == null : "return instructions do not have debug information";
+
+                assert curLastOp instanceof LIROp1 : "return must be LIROp1";
+                CiValue returnOpr = ((LIROp1) curLastOp).operand();
+
+                for (int j = block.numberOfPreds() - 1; j >= 0; j--) {
+                    LIRBlock pred = block.predAt(j);
+                    List<LIRInstruction> predInstructions = pred.lir().instructionsList();
+                    LIRInstruction predLastOp = predInstructions.get(predInstructions.size() - 1);
+
+                    if (predLastOp.code == LIROpcode.Branch) {
+                        assert predLastOp instanceof LIRBranch : "branch must be LIRBranch";
+                        LIRBranch predLastBranch = (LIRBranch) predLastOp;
+
+                        if (predLastBranch.block() == block && predLastBranch.cond() == Condition.TRUE && predLastBranch.info == null) {
+                            // replace the jump to a return with a direct return
+                            // Note: currently the edge between the blocks is not deleted
+                            predInstructions.set(predInstructions.size() - 1, new LIROp1(LIROpcode.Return, returnOpr));
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private boolean verify(List<LIRBlock> code) {
+        for (LIRBlock block : code) {
+            List<LIRInstruction> instructions = block.lir().instructionsList();
+
+            for (LIRInstruction instr : instructions) {
+                if (instr instanceof LIRBranch) {
+                    LIRBranch opBranch = (LIRBranch) instr;
+                    assert opBranch.block() == null || opBranch.block().blockID() == -1 || code.contains(opBranch.block()) : "missing successor branch from: " + block + " to: " + opBranch.block();
+                    assert opBranch.unorderedBlock() == null || opBranch.unorderedBlock().blockID() == -1 || code.contains(opBranch.unorderedBlock()) : "missing successor branch from: " + block + " to: " + opBranch.unorderedBlock();
+                }
+            }
+
+            for (LIRBlock sux : block.blockSuccessors()) {
+                assert code.contains(sux) : "missing successor from: " + block + "to: " + sux;
+            }
+
+            for (LIRBlock pred : block.blockPredecessors()) {
+                assert code.contains(pred) : "missing predecessor from: " + block + "to: " + pred;
+            }
+        }
+
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/EdgeMoveOptimizer.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.alloc;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.lir.*;
+
+/**
+ * This class optimizes moves, particularly those that result from eliminating SSA form.
+ *
+ * When a block has more than one predecessor, and all predecessors end with
+ * the {@linkplain #same(LIRInstruction, LIRInstruction) same} sequence of
+ * {@linkplain LIROpcode#Move move} instructions, then these sequences
+ * can be replaced with a single copy of the sequence at the beginning of the block.
+ *
+ * Similarly, when a block has more than one successor, then same sequences of
+ * moves at the beginning of the successors can be placed once at the end of
+ * the block. But because the moves must be inserted before all branch
+ * instructions, this works only when there is exactly one conditional branch
+ * at the end of the block (because the moves must be inserted before all
+ * branches, but after all compares).
+ *
+ * This optimization affects all kind of moves (reg->reg, reg->stack and
+ * stack->reg). Because this optimization works best when a block contains only
+ * a few moves, it has a huge impact on the number of blocks that are totally
+ * empty.
+ *
+ * @author Christian Wimmer (original HotSpot implementation)
+ * @author Thomas Wuerthinger
+ * @author Doug Simon
+ */
+final class EdgeMoveOptimizer {
+
+    /**
+     * Optimizes moves on block edges.
+     *
+     * @param blockList a list of blocks whose moves should be optimized
+     */
+    public static void optimize(List<LIRBlock> blockList) {
+        EdgeMoveOptimizer optimizer = new EdgeMoveOptimizer();
+
+        // ignore the first block in the list (index 0 is not processed)
+        for (int i = blockList.size() - 1; i >= 1; i--) {
+            LIRBlock block = blockList.get(i);
+
+            if (block.numberOfPreds() > 1) {
+                optimizer.optimizeMovesAtBlockEnd(block);
+            }
+            if (block.numberOfSux() == 2) {
+                optimizer.optimizeMovesAtBlockBegin(block);
+            }
+        }
+    }
+
+    private final List<List<LIRInstruction>> edgeInstructionSeqences;
+
+    private EdgeMoveOptimizer() {
+        edgeInstructionSeqences = new ArrayList<List<LIRInstruction>>(4);
+    }
+
+    /**
+     * Determines if two operations are both {@linkplain LIROpcode#Move moves}
+     * that have the same {@linkplain LIROp1#operand() source} and {@linkplain LIROp1#result() destination}
+     * operands and they have the same {@linkplain LIRInstruction#info debug info}.
+     *
+     * @param op1 the first instruction to compare
+     * @param op2 the second instruction to compare
+     * @return {@code true} if {@code op1} and {@code op2} are the same by the above algorithm
+     */
+    private boolean same(LIRInstruction op1, LIRInstruction op2) {
+        assert op1 != null;
+        assert op2 != null;
+
+        if (op1.code == LIROpcode.Move && op2.code == LIROpcode.Move) {
+            assert op1 instanceof LIROp1 : "move must be LIROp1";
+            assert op2 instanceof LIROp1 : "move must be LIROp1";
+            LIROp1 move1 = (LIROp1) op1;
+            LIROp1 move2 = (LIROp1) op2;
+            if (move1.info == move2.info && move1.operand().equals(move2.operand()) && move1.result().equals(move2.result())) {
+                // these moves are exactly equal and can be optimized
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Moves the longest {@linkplain #same common} subsequence at the end all
+     * predecessors of {@code block} to the start of {@code block}.
+     */
+    private void optimizeMovesAtBlockEnd(LIRBlock block) {
+        if (block.isPredecessor(block)) {
+            // currently we can't handle this correctly.
+            return;
+        }
+
+        // clear all internal data structures
+        edgeInstructionSeqences.clear();
+
+        int numPreds = block.numberOfPreds();
+        assert numPreds > 1 : "do not call otherwise";
+
+        // setup a list with the LIR instructions of all predecessors
+        for (int i = 0; i < numPreds; i++) {
+            LIRBlock pred = block.predAt(i);
+            assert pred != null;
+            assert pred.lir() != null;
+            List<LIRInstruction> predInstructions = pred.lir().instructionsList();
+
+            if (pred.numberOfSux() != 1) {
+                // this can happen with switch-statements where multiple edges are between
+                // the same blocks.
+                return;
+            }
+
+            if (predInstructions.get(predInstructions.size() - 1).code == LIROpcode.Xir) {
+                return;
+            }
+
+            assert pred.suxAt(0) == block : "invalid control flow";
+            assert predInstructions.get(predInstructions.size() - 1).code == LIROpcode.Branch : "block with successor must end with branch" + predInstructions.get(predInstructions.size() - 1);
+            assert predInstructions.get(predInstructions.size() - 1) instanceof LIRBranch : "branch must be LIROpBranch";
+            assert ((LIRBranch) predInstructions.get(predInstructions.size() - 1)).cond() == Condition.TRUE : "block must end with unconditional branch";
+
+            if (predInstructions.get(predInstructions.size() - 1).info != null) {
+                // can not optimize instructions that have debug info
+                return;
+            }
+
+            // ignore the unconditional branch at the end of the block
+            List<LIRInstruction> seq = predInstructions.subList(0, predInstructions.size() - 1);
+            edgeInstructionSeqences.add(seq);
+        }
+
+        // process lir-instructions while all predecessors end with the same instruction
+        while (true) {
+            List<LIRInstruction> seq = edgeInstructionSeqences.get(0);
+            if (seq.isEmpty()) {
+                return;
+            }
+
+            LIRInstruction op = last(seq);
+            for (int i = 1; i < numPreds; ++i) {
+                List<LIRInstruction> otherSeq = edgeInstructionSeqences.get(i);
+                if (otherSeq.isEmpty() || !same(op, last(otherSeq))) {
+                    return;
+                }
+            }
+
+            // insert the instruction at the beginning of the current block
+            block.lir().insertBefore(1, op);
+
+            // delete the instruction at the end of all predecessors
+            for (int i = 0; i < numPreds; i++) {
+                seq = edgeInstructionSeqences.get(i);
+                removeLast(seq);
+            }
+        }
+    }
+
+    /**
+     * Moves the longest {@linkplain #same common} subsequence at the start of all
+     * successors of {@code block} to the end of {@code block} just prior to the
+     * branch instruction ending {@code block}.
+     */
+    private void optimizeMovesAtBlockBegin(LIRBlock block) {
+
+        edgeInstructionSeqences.clear();
+        int numSux = block.numberOfSux();
+
+        List<LIRInstruction> instructions = block.lir().instructionsList();
+
+        assert numSux == 2 : "method should not be called otherwise";
+
+        if (instructions.get(instructions.size() - 1).code == LIROpcode.Xir) {
+            // cannot optimize when last instruction is Xir.
+            return;
+        }
+
+        assert instructions.get(instructions.size() - 1).code == LIROpcode.Branch : "block with successor must end with branch block=B" + block.blockID();
+        assert instructions.get(instructions.size() - 1) instanceof LIRBranch : "branch must be LIROpBranch";
+        assert ((LIRBranch) instructions.get(instructions.size() - 1)).cond() == Condition.TRUE : "block must end with unconditional branch";
+
+        if (instructions.get(instructions.size() - 1).info != null) {
+            // cannot optimize instructions when debug info is needed
+            return;
+        }
+
+        LIRInstruction branch = instructions.get(instructions.size() - 2);
+        if (branch.info != null || (branch.code != LIROpcode.Branch && branch.code != LIROpcode.CondFloatBranch)) {
+            // not a valid case for optimization
+            // currently, only blocks that end with two branches (conditional branch followed
+            // by unconditional branch) are optimized
+            return;
+        }
+
+        // now it is guaranteed that the block ends with two branch instructions.
+        // the instructions are inserted at the end of the block before these two branches
+        int insertIdx = instructions.size() - 2;
+
+        if (GraalOptions.DetailedAsserts && false) { // not true anymore with guards
+            for (int i = insertIdx - 1; i >= 0; i--) {
+                LIRInstruction op = instructions.get(i);
+                if ((op.code == LIROpcode.Branch || op.code == LIROpcode.CondFloatBranch) && ((LIRBranch) op).block() != null) {
+                    throw new Error("block with two successors can have only two branch instructions : error in " + block);
+                }
+            }
+        }
+
+        // setup a list with the lir-instructions of all successors
+        for (int i = 0; i < numSux; i++) {
+            LIRBlock sux = block.suxAt(i);
+            List<LIRInstruction> suxInstructions = sux.lir().instructionsList();
+
+            assert suxInstructions.get(0).code == LIROpcode.Label : "block must start with label";
+
+            if (sux.numberOfPreds() != 1) {
+                // this can happen with switch-statements where multiple edges are between
+                // the same blocks.
+                return;
+            }
+            assert sux.predAt(0) == block : "invalid control flow";
+
+            // ignore the label at the beginning of the block
+            List<LIRInstruction> seq = suxInstructions.subList(1, suxInstructions.size());
+            edgeInstructionSeqences.add(seq);
+        }
+
+        // process LIR instructions while all successors begin with the same instruction
+        while (true) {
+            List<LIRInstruction> seq = edgeInstructionSeqences.get(0);
+            if (seq.isEmpty()) {
+                return;
+            }
+
+            LIRInstruction op = first(seq);
+            for (int i = 1; i < numSux; i++) {
+                List<LIRInstruction> otherSeq = edgeInstructionSeqences.get(i);
+                if (otherSeq.isEmpty() || !same(op, first(otherSeq))) {
+                    // these instructions are different and cannot be optimized .
+                    // no further optimization possible
+                    return;
+                }
+            }
+
+            // insert instruction at end of current block
+            block.lir().insertBefore(insertIdx, op);
+            insertIdx++;
+
+            // delete the instructions at the beginning of all successors
+            for (int i = 0; i < numSux; i++) {
+                seq = edgeInstructionSeqences.get(i);
+                removeFirst(seq);
+            }
+        }
+    }
+
+    /**
+     * Gets the first element from a LIR instruction sequence.
+     */
+    private static LIRInstruction first(List<LIRInstruction> seq) {
+        return seq.get(0);
+    }
+
+    /**
+     * Gets the last element from a LIR instruction sequence.
+     */
+    private static LIRInstruction last(List<LIRInstruction> seq) {
+        return seq.get(seq.size() - 1);
+    }
+
+    /**
+     * Removes the first element from a LIR instruction sequence.
+     */
+    private static void removeFirst(List<LIRInstruction> seq) {
+        seq.remove(0);
+    }
+
+    /**
+     * Removes the last element from a LIR instruction sequence.
+     */
+    private static void removeLast(List<LIRInstruction> seq) {
+        seq.remove(seq.size() - 1);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/Interval.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,1173 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.alloc;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.lir.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.sun.cri.ci.*;
+
+/**
+ * Represents an interval in the {@linkplain LinearScan linear scan register allocator}.
+ *
+ * @author Thomas Wuerthinger
+ * @author Doug Simon
+ */
+public final class Interval {
+
+    /**
+     * A pair of intervals.
+     */
+    static final class Pair {
+        public final Interval first;
+        public final Interval second;
+        public Pair(Interval first, Interval second) {
+            this.first = first;
+            this.second = second;
+        }
+    }
+
+    /**
+     * A set of interval lists, one per {@linkplain RegisterBinding binding} type.
+     */
+    static final class RegisterBindingLists {
+
+        /**
+         * List of intervals whose binding is currently {@link RegisterBinding#Fixed}.
+         */
+        public Interval fixed;
+
+        /**
+         * List of intervals whose binding is currently {@link RegisterBinding#Any}.
+         */
+        public Interval any;
+
+        public RegisterBindingLists(Interval fixed, Interval any) {
+            this.fixed = fixed;
+            this.any = any;
+        }
+
+        /**
+         * Gets the list for a specified binding.
+         *
+         * @param binding specifies the list to be returned
+         * @return the list of intervals whose binding is {@code binding}
+         */
+        public Interval get(RegisterBinding binding) {
+            if (binding == RegisterBinding.Any) {
+                return any;
+            }
+            assert binding == RegisterBinding.Fixed;
+            return fixed;
+        }
+
+        /**
+         * Sets the list for a specified binding.
+         *
+         * @param binding specifies the list to be replaced
+         * @param a list of intervals whose binding is {@code binding}
+         */
+        public void set(RegisterBinding binding, Interval list) {
+            assert list != null;
+            if (binding == RegisterBinding.Any) {
+                any = list;
+            } else {
+                assert binding == RegisterBinding.Fixed;
+                fixed = list;
+            }
+        }
+
+        /**
+         * Adds an interval to a list sorted by {@linkplain Interval#currentFrom() current from} positions.
+         *
+         * @param binding specifies the list to be updated
+         * @param interval the interval to add
+         */
+        public void addToListSortedByCurrentFromPositions(RegisterBinding binding, Interval interval) {
+            Interval list = get(binding);
+            Interval prev = null;
+            Interval cur = list;
+            while (cur.currentFrom() < interval.currentFrom()) {
+                prev = cur;
+                cur = cur.next;
+            }
+            Interval result = list;
+            if (prev == null) {
+                // add to head of list
+                result = interval;
+            } else {
+                // add before 'cur'
+                prev.next = interval;
+            }
+            interval.next = cur;
+            set(binding, result);
+        }
+
+        /**
+         * Adds an interval to a list sorted by {@linkplain Interval#from() start} positions and
+         * {@linkplain Interval#firstUsage(RegisterPriority) first usage} positions.
+         *
+         * @param binding specifies the list to be updated
+         * @param interval the interval to add
+         */
+        public void addToListSortedByStartAndUsePositions(RegisterBinding binding, Interval interval) {
+            Interval list = get(binding);
+            Interval prev = null;
+            Interval cur = list;
+            while (cur.from() < interval.from() || (cur.from() == interval.from() && cur.firstUsage(RegisterPriority.None) < interval.firstUsage(RegisterPriority.None))) {
+                prev = cur;
+                cur = cur.next;
+            }
+            if (prev == null) {
+                list = interval;
+            } else {
+                prev.next = interval;
+            }
+            interval.next = cur;
+            set(binding, list);
+        }
+
+        /**
+         * Removes an interval from a list.
+         *
+         * @param binding specifies the list to be updated
+         * @param interval the interval to remove
+         */
+        public void remove(RegisterBinding binding, Interval i) {
+            Interval list = get(binding);
+            Interval prev = null;
+            Interval cur = list;
+            while (cur != i) {
+                assert cur != null && cur != Interval.EndMarker : "interval has not been found in list: " + i;
+                prev = cur;
+                cur = cur.next;
+            }
+            if (prev == null) {
+                set(binding, cur.next);
+            } else {
+                prev.next = cur.next;
+            }
+        }
+    }
+
+    /**
+     * Constants denoting the register usage priority for an interval.
+     * The constants are declared in increasing order of priority are
+     * are used to optimize spilling when multiple overlapping intervals
+     * compete for limited registers.
+     */
+    enum RegisterPriority {
+        /**
+         * No special reason for an interval to be allocated a register.
+         */
+        None,
+
+        /**
+         * Priority level for intervals live at the end of a loop.
+         */
+        LiveAtLoopEnd,
+
+        /**
+         * Priority level for intervals that should be allocated to a register.
+         */
+        ShouldHaveRegister,
+
+        /**
+         * Priority level for intervals that must be allocated to a register.
+         */
+        MustHaveRegister;
+
+        public static final RegisterPriority[] VALUES = values();
+
+        /**
+         * Determines if this priority is higher than or equal to a given priority.
+         */
+        public boolean greaterEqual(RegisterPriority other) {
+            return ordinal() >= other.ordinal();
+        }
+
+        /**
+         * Determines if this priority is lower than a given priority.
+         */
+        public boolean lessThan(RegisterPriority other) {
+            return ordinal() < other.ordinal();
+        }
+    }
+
+    /**
+     * Constants denoting whether an interval is bound to a specific register. This models
+     * platform dependencies on register usage for certain instructions.
+     */
+    enum RegisterBinding {
+        /**
+         * Interval is bound to a specific register as required by the platform.
+         */
+        Fixed,
+
+        /**
+         * Interval has no specific register requirements.
+         */
+        Any;
+
+        public static final RegisterBinding[] VALUES = values();
+    }
+
+    /**
+     * Constants denoting the linear-scan states an interval may be in with respect to the
+     * {@linkplain Interval#from() start} {@code position} of the interval being processed.
+     */
+    enum State {
+        /**
+         * An interval that starts after {@code position}.
+         */
+        Unhandled,
+
+        /**
+         * An interval that {@linkplain Interval#covers covers} {@code position} and has an assigned register.
+         */
+        Active,
+
+        /**
+         * An interval that starts before and ends after {@code position} but does not
+         * {@linkplain Interval#covers cover} it due to a lifetime hole.
+         */
+        Inactive,
+
+        /**
+         * An interval that ends before {@code position} or is spilled to memory.
+         */
+        Handled;
+    }
+
+    /**
+     * Constants used in optimization of spilling of an interval.
+     */
+    enum SpillState {
+        /**
+         * Starting state of calculation: no definition found yet.
+         */
+        NoDefinitionFound,
+
+        /**
+         * One definition has already been found. Two consecutive definitions are treated as one
+         * (e.g. a consecutive move and add because of two-operand LIR form).
+         * The position of this definition is given by {@link Interval#spillDefinitionPos()}.
+         */
+        NoSpillStore,
+
+        /**
+         * One spill move has already been inserted.
+         */
+        OneSpillStore,
+
+        /**
+         * The interval should be stored immediately after its definition to prevent
+         * multiple redundant stores.
+         */
+        StoreAtDefinition,
+
+        /**
+         * The interval starts in memory (e.g. method parameter), so a store is never necessary.
+         */
+        StartInMemory,
+
+        /**
+         * The interval has more than one definition (e.g. resulting from phi moves), so stores
+         * to memory are not optimized.
+         */
+        NoOptimization
+    }
+
+    /**
+     * List of use positions. Each entry in the list records the use position and register
+     * priority associated with the use position. The entries in the list are in descending
+     * order of use position.
+     *
+     * @author Doug Simon
+     */
+    public static final class UsePosList {
+        private IntList list;
+
+        /**
+         * Creates a use list.
+         *
+         * @param initialCapacity the initial capacity of the list in terms of entries
+         */
+        public UsePosList(int initialCapacity) {
+            list = new IntList(initialCapacity * 2);
+        }
+
+        private UsePosList(IntList list) {
+            this.list = list;
+        }
+
+        /**
+         * Splits this list around a given position. All entries in this list with a use position greater or equal than
+         * {@code splitPos} are removed from this list and added to the returned list.
+         *
+         * @param splitPos the position for the split
+         * @return a use position list containing all entries removed from this list that have a use position greater or equal
+         *         than {@code splitPos}
+         */
+        public UsePosList splitAt(int splitPos) {
+            int i = size() - 1;
+            int len = 0;
+            while (i >= 0 && usePos(i) < splitPos) {
+                --i;
+                len += 2;
+            }
+            int listSplitIndex = (i + 1) * 2;
+            IntList childList = list;
+            list = IntList.copy(this.list, listSplitIndex, len);
+            childList.setSize(listSplitIndex);
+            UsePosList child = new UsePosList(childList);
+            return child;
+        }
+
+        /**
+         * Gets the use position at a specified index in this list.
+         *
+         * @param index the index of the entry for which the use position is returned
+         * @return the use position of entry {@code index} in this list
+         */
+        public int usePos(int index) {
+            return list.get(index << 1);
+        }
+
+        /**
+         * Gets the register priority for the use position at a specified index in this list.
+         *
+         * @param index the index of the entry for which the register priority is returned
+         * @return the register priority of entry {@code index} in this list
+         */
+        public RegisterPriority registerPriority(int index) {
+            return RegisterPriority.VALUES[list.get((index << 1) + 1)];
+        }
+
+        public void add(int usePos, RegisterPriority registerPriority) {
+            assert list.size() == 0 || usePos(size() - 1) > usePos;
+            list.add(usePos);
+            list.add(registerPriority.ordinal());
+        }
+
+        public int size() {
+            return list.size() >> 1;
+        }
+
+        public void removeLowestUsePos() {
+            list.setSize(list.size() - 2);
+        }
+
+        public void setRegisterPriority(int index, RegisterPriority registerPriority) {
+            list.set(index * 2, registerPriority.ordinal());
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder buf = new StringBuilder("[");
+            for (int i = size() - 1; i >= 0; --i) {
+                if (buf.length() != 1) {
+                    buf.append(", ");
+                }
+                RegisterPriority prio = registerPriority(i);
+                buf.append(usePos(i)).append(" -> ").append(prio.ordinal()).append(':').append(prio);
+            }
+            return buf.append("]").toString();
+        }
+    }
+
+    /**
+     * The {@linkplain CiRegisterValue register} or {@linkplain CiVariable variable} for this interval prior to register allocation.
+     */
+    public final CiValue operand;
+
+    /**
+     * The {@linkplain OperandPool#operandNumber(CiValue) operand number} for this interval's {@linkplain #operand operand}.
+     */
+    public final int operandNumber;
+
+    /**
+     * The {@linkplain CiRegisterValue register}, {@linkplain CiStackSlot spill slot} or {@linkplain CiAddress address} assigned to this interval.
+     */
+    private CiValue location;
+
+    /**
+     * The stack slot to which all splits of this interval are spilled if necessary.
+     */
+    private CiStackSlot spillSlot;
+
+    /**
+     * The kind of this interval.
+     * Only valid if this is a {@linkplain #isVariable() variable}.
+     */
+    private CiKind kind;
+
+    /**
+     * The head of the list of ranges describing this interval. This list is sorted by {@linkplain LIRInstruction#id instruction ids}.
+     */
+    private Range first;
+
+    /**
+     * List of (use-positions, register-priorities) pairs, sorted by use-positions.
+     */
+    private UsePosList usePosList;
+
+    /**
+     * Iterator used to traverse the ranges of an interval.
+     */
+    private Range current;
+
+    /**
+     * Link to next interval in a sorted list of intervals that ends with {@link #EndMarker}.
+     */
+    Interval next;
+
+    /**
+     * The linear-scan state of this interval.
+     */
+    State state;
+
+    private int cachedTo; // cached value: to of last range (-1: not cached)
+
+    /**
+     * The interval from which this one is derived. If this is a {@linkplain #isSplitParent() split parent}, it points to itself.
+     */
+    private Interval splitParent;
+
+    /**
+     * List of all intervals that are split off from this interval. This is only used if this is a {@linkplain #isSplitParent() split parent}.
+     */
+    private List<Interval> splitChildren = Collections.emptyList();
+
+    /**
+     * Current split child that has been active or inactive last (always stored in split parents).
+     */
+    private Interval currentSplitChild;
+
+    /**
+     * Specifies if move is inserted between currentSplitChild and this interval when interval gets active the first time.
+     */
+    private boolean insertMoveWhenActivated;
+
+    /**
+     * For spill move optimization.
+     */
+    private SpillState spillState;
+
+    /**
+     * Position where this interval is defined (if defined only once).
+     */
+    private int spillDefinitionPos;
+
+    /**
+     * This interval should be assigned the same location as the hint interval.
+     */
+    private Interval locationHint;
+
+    void assignLocation(CiValue location) {
+        if (location.isRegister()) {
+            assert this.location == null : "cannot re-assign location for " + this;
+            if (location.kind == CiKind.Illegal && kind != CiKind.Illegal) {
+                location = location.asRegister().asValue(kind);
+            }
+        } else {
+            assert this.location == null || this.location.isRegister() : "cannot re-assign location for " + this;
+            assert location.isStackSlot();
+            assert location.kind != CiKind.Illegal;
+            assert location.kind == this.kind;
+        }
+        this.location = location;
+    }
+
+    /**
+     * Gets the {@linkplain CiRegisterValue register}, {@linkplain CiStackSlot spill slot} or {@linkplain CiAddress address} assigned to this interval.
+     */
+    public CiValue location() {
+        return location;
+    }
+
+    public CiKind kind() {
+        assert !operand.isRegister() : "cannot access type for fixed interval";
+        return kind;
+    }
+
+    void setKind(CiKind kind) {
+        assert operand.isRegister() || this.kind == CiKind.Illegal || this.kind == kind : "overwriting existing type";
+        assert kind == kind.stackKind() || kind == CiKind.Short : "these kinds should have int type registers";
+        this.kind = kind;
+    }
+
+    public Range first() {
+        return first;
+    }
+
+    int from() {
+        return first.from;
+    }
+
+    int to() {
+        if (cachedTo == -1) {
+            cachedTo = calcTo();
+        }
+        assert cachedTo == calcTo() : "invalid cached value";
+        return cachedTo;
+    }
+
+    int numUsePositions() {
+        return usePosList.size();
+    }
+
+    void setLocationHint(Interval interval) {
+        locationHint = interval;
+    }
+
+    boolean isSplitParent() {
+        return splitParent == this;
+    }
+
+    boolean isSplitChild() {
+        return splitParent != this;
+    }
+
+    /**
+     * Gets the split parent for this interval.
+     */
+    public Interval splitParent() {
+        assert splitParent.isSplitParent() : "not a split parent: " + this;
+        return splitParent;
+    }
+
+    /**
+     * Gets the canonical spill slot for this interval.
+     */
+    CiStackSlot spillSlot() {
+        return splitParent().spillSlot;
+    }
+
+    void setSpillSlot(CiStackSlot slot) {
+        assert splitParent().spillSlot == null : "connot overwrite existing spill slot";
+        splitParent().spillSlot = slot;
+    }
+
+    Interval currentSplitChild() {
+        return splitParent().currentSplitChild;
+    }
+
+    void makeCurrentSplitChild() {
+        splitParent().currentSplitChild = this;
+    }
+
+    boolean insertMoveWhenActivated() {
+        return insertMoveWhenActivated;
+    }
+
+    void setInsertMoveWhenActivated(boolean b) {
+        insertMoveWhenActivated = b;
+    }
+
+    // for spill optimization
+    public SpillState spillState() {
+        return splitParent().spillState;
+    }
+
+    int spillDefinitionPos() {
+        return splitParent().spillDefinitionPos;
+    }
+
+    void setSpillState(SpillState state) {
+        assert state.ordinal() >= spillState().ordinal() : "state cannot decrease";
+        splitParent().spillState = state;
+    }
+
+    void setSpillDefinitionPos(int pos) {
+        assert spillDefinitionPos() == -1 : "cannot set the position twice";
+        splitParent().spillDefinitionPos = pos;
+    }
+
+    // returns true if this interval has a shadow copy on the stack that is always correct
+    boolean alwaysInMemory() {
+        return splitParent().spillState == SpillState.StoreAtDefinition || splitParent().spillState == SpillState.StartInMemory;
+    }
+
+    void removeFirstUsePos() {
+        usePosList.removeLowestUsePos();
+    }
+
+    // test intersection
+    boolean intersects(Interval i) {
+        return first.intersects(i.first);
+    }
+
+    int intersectsAt(Interval i) {
+        return first.intersectsAt(i.first);
+    }
+
+    // range iteration
+    void rewindRange() {
+        current = first;
+    }
+
+    void nextRange() {
+        assert this != EndMarker : "not allowed on sentinel";
+        current = current.next;
+    }
+
+    int currentFrom() {
+        return current.from;
+    }
+
+    int currentTo() {
+        return current.to;
+    }
+
+    boolean currentAtEnd() {
+        return current == Range.EndMarker;
+    }
+
+    boolean currentIntersects(Interval it) {
+        return current.intersects(it.current);
+    }
+
+    int currentIntersectsAt(Interval it) {
+        return current.intersectsAt(it.current);
+    }
+
+    /**
+     * Sentinel interval to denote the end of an interval list.
+     */
+    static final Interval EndMarker = new Interval(CiValue.IllegalValue, -1);
+
+    Interval(CiValue operand, int operandNumber) {
+        GraalMetrics.LSRAIntervalsCreated++;
+        assert operand != null;
+        this.operand = operand;
+        this.operandNumber = operandNumber;
+        if (operand.isRegister()) {
+            location = operand;
+        } else {
+            assert operand.isIllegal() || operand.isVariable();
+        }
+        this.kind = CiKind.Illegal;
+        this.first = Range.EndMarker;
+        this.usePosList = new UsePosList(4);
+        this.current = Range.EndMarker;
+        this.next = EndMarker;
+        this.cachedTo = -1;
+        this.spillState = SpillState.NoDefinitionFound;
+        this.spillDefinitionPos = -1;
+        splitParent = this;
+        currentSplitChild = this;
+    }
+
+    int calcTo() {
+        assert first != Range.EndMarker : "interval has no range";
+
+        Range r = first;
+        while (r.next != Range.EndMarker) {
+            r = r.next;
+        }
+        return r.to;
+    }
+
+    // consistency check of split-children
+    boolean checkSplitChildren() {
+        if (!splitChildren.isEmpty()) {
+            assert isSplitParent() : "only split parents can have children";
+
+            for (int i = 0; i < splitChildren.size(); i++) {
+                Interval i1 = splitChildren.get(i);
+
+                assert i1.splitParent() == this : "not a split child of this interval";
+                assert i1.kind() == kind() : "must be equal for all split children";
+                assert i1.spillSlot() == spillSlot() : "must be equal for all split children";
+
+                for (int j = i + 1; j < splitChildren.size(); j++) {
+                    Interval i2 = splitChildren.get(j);
+
+                    assert i1.operand != i2.operand : "same register number";
+
+                    if (i1.from() < i2.from()) {
+                        assert i1.to() <= i2.from() && i1.to() < i2.to() : "intervals overlapping";
+                    } else {
+                        assert i2.from() < i1.from() : "intervals start at same opId";
+                        assert i2.to() <= i1.from() && i2.to() < i1.to() : "intervals overlapping";
+                    }
+                }
+            }
+        }
+
+        return true;
+    }
+
+    public Interval locationHint(boolean searchSplitChild, LinearScan allocator) {
+        if (!searchSplitChild) {
+            return locationHint;
+        }
+
+        if (locationHint != null) {
+            assert locationHint.isSplitParent() : "ony split parents are valid hint registers";
+
+            if (locationHint.location != null && locationHint.location.isRegister()) {
+                return locationHint;
+            } else if (!locationHint.splitChildren.isEmpty()) {
+                // search the first split child that has a register assigned
+                int len = locationHint.splitChildren.size();
+                for (int i = 0; i < len; i++) {
+                    Interval interval = locationHint.splitChildren.get(i);
+                    if (interval.location != null && interval.location.isRegister()) {
+                        return interval;
+                    }
+                }
+            }
+        }
+
+        // no hint interval found that has a register assigned
+        return null;
+    }
+
+    Interval getSplitChildAtOpId(int opId, LIRInstruction.OperandMode mode, LinearScan allocator) {
+        assert isSplitParent() : "can only be called for split parents";
+        assert opId >= 0 : "invalid opId (method cannot be called for spill moves)";
+
+        if (splitChildren.isEmpty()) {
+            assert this.covers(opId, mode) : this + " does not cover " + opId;
+            return this;
+        } else {
+            Interval result = null;
+            int len = splitChildren.size();
+
+            // in outputMode, the end of the interval (opId == cur.to()) is not valid
+            int toOffset = (mode == LIRInstruction.OperandMode.Output ? 0 : 1);
+
+            int i;
+            for (i = 0; i < len; i++) {
+                Interval cur = splitChildren.get(i);
+                if (cur.from() <= opId && opId < cur.to() + toOffset) {
+                    if (i > 0) {
+                        // exchange current split child to start of list (faster access for next call)
+                        Util.atPutGrow(splitChildren, i, splitChildren.get(0), null);
+                        Util.atPutGrow(splitChildren, 0, cur, null);
+                    }
+
+                    // interval found
+                    result = cur;
+                    break;
+                }
+            }
+
+            assert checkSplitChild(result, opId, allocator, toOffset, mode);
+            return result;
+        }
+    }
+
+    private boolean checkSplitChild(Interval result, int opId, LinearScan allocator, int toOffset, LIRInstruction.OperandMode mode) {
+        if (result == null) {
+            // this is an error
+            StringBuilder msg = new StringBuilder(this.toString()).append(" has no child at ").append(opId);
+            if (!splitChildren.isEmpty()) {
+                Interval first = splitChildren.get(0);
+                Interval last = splitChildren.get(splitChildren.size() - 1);
+                msg.append(" (first = ").append(first).append(", last = ").append(last).append(")");
+            }
+            throw new CiBailout("Linear Scan Error: " + msg);
+        }
+
+        if (!splitChildren.isEmpty()) {
+            for (Interval interval : splitChildren) {
+                if (interval != result && interval.from() <= opId && opId < interval.to() + toOffset) {
+                    TTY.println(String.format("two valid result intervals found for opId %d: %d and %d", opId, result.operandNumber, interval.operandNumber));
+                    TTY.println(result.logString(allocator));
+                    TTY.println(interval.logString(allocator));
+                    throw new CiBailout("two valid result intervals found");
+                }
+            }
+        }
+        assert result.covers(opId, mode) : "opId not covered by interval";
+        return true;
+    }
+
+    // returns the last split child that ends before the given opId
+    Interval getSplitChildBeforeOpId(int opId) {
+        assert opId >= 0 : "invalid opId";
+
+        Interval parent = splitParent();
+        Interval result = null;
+
+        assert !parent.splitChildren.isEmpty() : "no split children available";
+        int len = parent.splitChildren.size();
+
+        for (int i = len - 1; i >= 0; i--) {
+            Interval cur = parent.splitChildren.get(i);
+            if (cur.to() <= opId && (result == null || result.to() < cur.to())) {
+                result = cur;
+            }
+        }
+
+        assert result != null : "no split child found";
+        return result;
+    }
+
+    // checks if opId is covered by any split child
+    boolean splitChildCovers(int opId, LIRInstruction.OperandMode mode) {
+        assert isSplitParent() : "can only be called for split parents";
+        assert opId >= 0 : "invalid opId (method can not be called for spill moves)";
+
+        if (splitChildren.isEmpty()) {
+            // simple case if interval was not split
+            return covers(opId, mode);
+
+        } else {
+            // extended case: check all split children
+            int len = splitChildren.size();
+            for (int i = 0; i < len; i++) {
+                Interval cur = splitChildren.get(i);
+                if (cur.covers(opId, mode)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+    // Note: use positions are sorted descending . first use has highest index
+    int firstUsage(RegisterPriority minRegisterPriority) {
+        assert operand.isVariable() : "cannot access use positions for fixed intervals";
+
+        for (int i = usePosList.size() - 1; i >= 0; --i) {
+            RegisterPriority registerPriority = usePosList.registerPriority(i);
+            if (registerPriority.greaterEqual(minRegisterPriority)) {
+                return usePosList.usePos(i);
+            }
+        }
+        return Integer.MAX_VALUE;
+    }
+
+    int nextUsage(RegisterPriority minRegisterPriority, int from) {
+        assert operand.isVariable() : "cannot access use positions for fixed intervals";
+
+        for (int i = usePosList.size() - 1; i >= 0; --i) {
+            int usePos = usePosList.usePos(i);
+            if (usePos >= from && usePosList.registerPriority(i).greaterEqual(minRegisterPriority)) {
+                return usePos;
+            }
+        }
+        return Integer.MAX_VALUE;
+    }
+
+    int nextUsageExact(RegisterPriority exactRegisterPriority, int from) {
+        assert operand.isVariable() : "cannot access use positions for fixed intervals";
+
+        for (int i = usePosList.size() - 1; i >= 0; --i) {
+            int usePos = usePosList.usePos(i);
+            if (usePos >= from && usePosList.registerPriority(i) == exactRegisterPriority) {
+                return usePos;
+            }
+        }
+        return Integer.MAX_VALUE;
+    }
+
+    int previousUsage(RegisterPriority minRegisterPriority, int from) {
+        assert operand.isVariable() : "cannot access use positions for fixed intervals";
+
+        int prev = 0;
+        for (int i = usePosList.size() - 1; i >= 0; --i) {
+            int usePos = usePosList.usePos(i);
+            if (usePos > from) {
+                return prev;
+            }
+            if (usePosList.registerPriority(i).greaterEqual(minRegisterPriority)) {
+                prev = usePos;
+            }
+        }
+        return prev;
+    }
+
+    void addUsePos(int pos, RegisterPriority registerPriority) {
+        assert covers(pos, LIRInstruction.OperandMode.Input) : "use position not covered by live range";
+
+        // do not add use positions for precolored intervals because they are never used
+        if (registerPriority != RegisterPriority.None && operand.isVariable()) {
+            if (GraalOptions.DetailedAsserts) {
+                for (int i = 0; i < usePosList.size(); i++) {
+                    assert pos <= usePosList.usePos(i) : "already added a use-position with lower position";
+                    if (i > 0) {
+                        assert usePosList.usePos(i) < usePosList.usePos(i - 1) : "not sorted descending";
+                    }
+                }
+            }
+
+            // Note: addUse is called in descending order, so list gets sorted
+            // automatically by just appending new use positions
+            int len = usePosList.size();
+            if (len == 0 || usePosList.usePos(len - 1) > pos) {
+                usePosList.add(pos, registerPriority);
+            } else if (usePosList.registerPriority(len - 1).lessThan(registerPriority)) {
+                assert usePosList.usePos(len - 1) == pos : "list not sorted correctly";
+                usePosList.setRegisterPriority(len - 1, registerPriority);
+            }
+        }
+    }
+
+    void addRange(int from, int to) {
+        assert from < to : "invalid range";
+        assert first() == Range.EndMarker || to < first().next.from : "not inserting at begin of interval";
+        assert from <= first().to : "not inserting at begin of interval";
+
+        if (first.from <= to) {
+            assert first != Range.EndMarker;
+            // join intersecting ranges
+            first.from = Math.min(from, first().from);
+            first.to = Math.max(to, first().to);
+        } else {
+            // insert new range
+            first = new Range(from, to, first());
+        }
+    }
+
+    Interval newSplitChild(LinearScan allocator) {
+        // allocate new interval
+        Interval parent = splitParent();
+        Interval result = allocator.createDerivedInterval(parent);
+        result.setKind(kind());
+
+        result.splitParent = parent;
+        result.setLocationHint(parent);
+
+        // insert new interval in children-list of parent
+        if (parent.splitChildren.isEmpty()) {
+            assert isSplitParent() : "list must be initialized at first split";
+
+            // Create new non-shared list
+            parent.splitChildren = new ArrayList<Interval>(4);
+            parent.splitChildren.add(this);
+        }
+        parent.splitChildren.add(result);
+
+        return result;
+    }
+
+    /**
+     * Splits this interval at a specified position and returns the remainder as a new <i>child</i> interval
+     * of this interval's {@linkplain #splitParent() parent} interval.
+     * <p>
+     * When an interval is split, a bi-directional link is established between the original <i>parent</i>
+     * interval and the <i>children</i> intervals that are split off this interval.
+     * When a split child is split again, the new created interval is a direct child
+     * of the original parent. That is, there is no tree of split children stored, just a flat list.
+     * All split children are spilled to the same {@linkplain #spillSlot spill slot}.
+     *
+     * @param splitPos the position at which to split this interval
+     * @param allocator the register allocator context
+     * @return the child interval split off from this interval
+     */
+    Interval split(int splitPos, LinearScan allocator) {
+        assert operand.isVariable() : "cannot split fixed intervals";
+
+        // allocate new interval
+        Interval result = newSplitChild(allocator);
+
+        // split the ranges
+        Range prev = null;
+        Range cur = first;
+        while (cur != Range.EndMarker && cur.to <= splitPos) {
+            prev = cur;
+            cur = cur.next;
+        }
+        assert cur != Range.EndMarker : "split interval after end of last range";
+
+        if (cur.from < splitPos) {
+            result.first = new Range(splitPos, cur.to, cur.next);
+            cur.to = splitPos;
+            cur.next = Range.EndMarker;
+
+        } else {
+            assert prev != null : "split before start of first range";
+            result.first = cur;
+            prev.next = Range.EndMarker;
+        }
+        result.current = result.first;
+        cachedTo = -1; // clear cached value
+
+        // split list of use positions
+        result.usePosList = usePosList.splitAt(splitPos);
+
+        if (GraalOptions.DetailedAsserts) {
+            for (int i = 0; i < usePosList.size(); i++) {
+                assert usePosList.usePos(i) < splitPos;
+            }
+            for (int i = 0; i < result.usePosList.size(); i++) {
+                assert result.usePosList.usePos(i) >= splitPos;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Splits this interval at a specified position and returns
+     * the head as a new interval (this interval is the tail).
+     *
+     * Currently, only the first range can be split, and the new interval must not have split positions
+     */
+    Interval splitFromStart(int splitPos, LinearScan allocator) {
+        assert operand.isVariable() : "cannot split fixed intervals";
+        assert splitPos > from() && splitPos < to() : "can only split inside interval";
+        assert splitPos > first.from && splitPos <= first.to : "can only split inside first range";
+        assert firstUsage(RegisterPriority.None) > splitPos : "can not split when use positions are present";
+
+        // allocate new interval
+        Interval result = newSplitChild(allocator);
+
+        // the new interval has only one range (checked by assertion above,
+        // so the splitting of the ranges is very simple
+        result.addRange(first.from, splitPos);
+
+        if (splitPos == first.to) {
+            assert first.next != Range.EndMarker : "must not be at end";
+            first = first.next;
+        } else {
+            first.from = splitPos;
+        }
+
+        return result;
+    }
+
+    // returns true if the opId is inside the interval
+    boolean covers(int opId, LIRInstruction.OperandMode mode) {
+        Range cur = first;
+
+        while (cur != Range.EndMarker && cur.to < opId) {
+            cur = cur.next;
+        }
+        if (cur != Range.EndMarker) {
+            assert cur.to != cur.next.from : "ranges not separated";
+
+            if (mode == LIRInstruction.OperandMode.Output) {
+                return cur.from <= opId && opId < cur.to;
+            } else {
+                return cur.from <= opId && opId <= cur.to;
+            }
+        }
+        return false;
+    }
+
+    // returns true if the interval has any hole between holeFrom and holeTo
+    // (even if the hole has only the length 1)
+    boolean hasHoleBetween(int holeFrom, int holeTo) {
+        assert holeFrom < holeTo : "check";
+        assert from() <= holeFrom && holeTo <= to() : "index out of interval";
+
+        Range cur = first;
+        while (cur != Range.EndMarker) {
+            assert cur.to < cur.next.from : "no space between ranges";
+
+            // hole-range starts before this range . hole
+            if (holeFrom < cur.from) {
+                return true;
+
+                // hole-range completely inside this range . no hole
+            } else {
+                if (holeTo <= cur.to) {
+                    return false;
+
+                    // overlapping of hole-range with this range . hole
+                } else {
+                    if (holeFrom <= cur.to) {
+                        return true;
+                    }
+                }
+            }
+
+            cur = cur.next;
+        }
+
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        String from = "?";
+        String to = "?";
+        if (first != null && first != Range.EndMarker) {
+            from = String.valueOf(from());
+            to = String.valueOf(to());
+        }
+        String location = this.location == null ? "" : "@" + this.location.name();
+        return operandNumber + ":" + operand + (operand.isRegister() ? "" : location) + "[" + from + "," + to + "]";
+    }
+
+    /**
+     * Gets the use position information for this interval.
+     */
+    public UsePosList usePosList() {
+        return usePosList;
+    }
+
+    /**
+     * Gets a single line string for logging the details of this interval to a log stream.
+     *
+     * @param allocator the register allocator context
+     */
+    public String logString(LinearScan allocator) {
+        StringBuilder buf = new StringBuilder(100);
+        buf.append(operandNumber).append(':').append(operand).append(' ');
+        if (!operand.isRegister()) {
+            if (location != null) {
+                buf.append("location{").append(location).append("} ");
+            }
+        }
+
+        buf.append("hints{").append(splitParent.operandNumber);
+        Interval hint = locationHint(false, allocator);
+        if (hint != null && hint.operandNumber != splitParent.operandNumber) {
+            buf.append(", ").append(hint.operandNumber);
+        }
+        buf.append("} ranges{");
+
+        // print ranges
+        Range cur = first;
+        while (cur != Range.EndMarker) {
+            if (cur != first) {
+                buf.append(", ");
+            }
+            buf.append(cur);
+            cur = cur.next;
+            assert cur != null : "range list not closed with range sentinel";
+        }
+        buf.append("} uses{");
+
+        // print use positions
+        int prev = 0;
+        for (int i = usePosList.size() - 1; i >= 0; --i) {
+            assert prev < usePosList.usePos(i) : "use positions not sorted";
+            if (i != usePosList.size() - 1) {
+                buf.append(", ");
+            }
+            buf.append(usePosList.usePos(i)).append(':').append(usePosList.registerPriority(i));
+            prev = usePosList.usePos(i);
+        }
+        return buf.append("} spill-state{").append(spillState()).append("}").toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/IntervalWalker.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.alloc;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.alloc.Interval.*;
+import com.oracle.max.graal.compiler.debug.*;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class IntervalWalker {
+
+    protected final GraalCompilation compilation;
+    protected final LinearScan allocator;
+
+    /**
+     * Sorted list of intervals, not live before the current position.
+     */
+    RegisterBindingLists unhandledLists;
+
+    /**
+     * Sorted list of intervals, live at the current position.
+     */
+    RegisterBindingLists activeLists;
+
+    /**
+     * Sorted list of intervals in a life time hole at the current position.
+     */
+    RegisterBindingLists inactiveLists;
+
+    /**
+     * The current interval (taken from the unhandled list) being processed.
+     */
+    protected Interval current;
+
+    /**
+     * The current position (intercept point through the intervals).
+     */
+    protected int currentPosition;
+
+    /**
+     * The binding of the current interval being processed.
+     */
+    protected RegisterBinding currentBinding;
+
+    /**
+     * Processes the {@linkplain #current} interval in an attempt to allocate a physical
+     * register to it and thus allow it to be moved to a list of {@linkplain #activeLists active} intervals.
+     *
+     * @return {@code true} if a register was allocated to the {@linkplain #current} interval
+     */
+    boolean activateCurrent() {
+        return true;
+    }
+
+    void walkBefore(int lirOpId) {
+        walkTo(lirOpId - 1);
+    }
+
+    void walk() {
+        walkTo(Integer.MAX_VALUE);
+    }
+
+    /**
+     * Creates a new interval walker.
+     *
+     * @param allocator the register allocator context
+     * @param unhandledFixed the list of unhandled {@linkplain RegisterBinding#Fixed fixed} intervals
+     * @param unhandledAny the list of unhandled {@linkplain RegisterBinding#Any non-fixed} intervals
+     */
+    IntervalWalker(LinearScan allocator, Interval unhandledFixed, Interval unhandledAny) {
+        this.compilation = allocator.compilation;
+        this.allocator = allocator;
+
+        unhandledLists = new RegisterBindingLists(unhandledFixed, unhandledAny);
+        activeLists = new RegisterBindingLists(Interval.EndMarker, Interval.EndMarker);
+        inactiveLists = new RegisterBindingLists(Interval.EndMarker, Interval.EndMarker);
+        currentPosition = -1;
+        current = null;
+        nextInterval();
+    }
+
+    void removeFromList(Interval interval) {
+        if (interval.state == State.Active) {
+            activeLists.remove(RegisterBinding.Any, interval);
+        } else {
+            assert interval.state == State.Inactive : "invalid state";
+            inactiveLists.remove(RegisterBinding.Any, interval);
+        }
+    }
+
+    void walkTo(State state, int from) {
+        assert state == State.Active || state == State.Inactive : "wrong state";
+        for (RegisterBinding binding : RegisterBinding.VALUES) {
+            Interval prevprev = null;
+            Interval prev = (state == State.Active) ? activeLists.get(binding) : inactiveLists.get(binding);
+            Interval next = prev;
+            while (next.currentFrom() <= from) {
+                Interval cur = next;
+                next = cur.next;
+
+                boolean rangeHasChanged = false;
+                while (cur.currentTo() <= from) {
+                    cur.nextRange();
+                    rangeHasChanged = true;
+                }
+
+                // also handle move from inactive list to active list
+                rangeHasChanged = rangeHasChanged || (state == State.Inactive && cur.currentFrom() <= from);
+
+                if (rangeHasChanged) {
+                    // remove cur from list
+                    if (prevprev == null) {
+                        if (state == State.Active) {
+                            activeLists.set(binding, next);
+                        } else {
+                            inactiveLists.set(binding, next);
+                        }
+                    } else {
+                        prevprev.next = next;
+                    }
+                    prev = next;
+                    if (cur.currentAtEnd()) {
+                        // move to handled state (not maintained as a list)
+                        cur.state = State.Handled;
+                        intervalMoved(cur, binding, state, State.Handled);
+                    } else if (cur.currentFrom() <= from) {
+                        // sort into active list
+                        activeLists.addToListSortedByCurrentFromPositions(binding, cur);
+                        cur.state = State.Active;
+                        if (prev == cur) {
+                            assert state == State.Active : "check";
+                            prevprev = prev;
+                            prev = cur.next;
+                        }
+                        intervalMoved(cur, binding, state, State.Active);
+                    } else {
+                        // sort into inactive list
+                        inactiveLists.addToListSortedByCurrentFromPositions(binding, cur);
+                        cur.state = State.Inactive;
+                        if (prev == cur) {
+                            assert state == State.Inactive : "check";
+                            prevprev = prev;
+                            prev = cur.next;
+                        }
+                        intervalMoved(cur, binding, state, State.Inactive);
+                    }
+                } else {
+                    prevprev = prev;
+                    prev = cur.next;
+                }
+            }
+        }
+    }
+
+    void nextInterval() {
+        RegisterBinding binding;
+        Interval any = unhandledLists.any;
+        Interval fixed = unhandledLists.fixed;
+
+        if (any != Interval.EndMarker) {
+            // intervals may start at same position . prefer fixed interval
+            binding = fixed != Interval.EndMarker && fixed.from() <= any.from() ? RegisterBinding.Fixed : RegisterBinding.Any;
+
+            assert binding == RegisterBinding.Fixed && fixed.from() <= any.from() || binding == RegisterBinding.Any && any.from() <= fixed.from() : "wrong interval!!!";
+            assert any == Interval.EndMarker || fixed == Interval.EndMarker || any.from() != fixed.from() || binding == RegisterBinding.Fixed : "if fixed and any-Interval start at same position, fixed must be processed first";
+
+        } else if (fixed != Interval.EndMarker) {
+            binding = RegisterBinding.Fixed;
+        } else {
+            current = null;
+            return;
+        }
+        currentBinding = binding;
+        current = unhandledLists.get(binding);
+        unhandledLists.set(binding, current.next);
+        current.next = Interval.EndMarker;
+        current.rewindRange();
+    }
+
+    void walkTo(int toOpId) {
+        assert currentPosition <= toOpId : "can not walk backwards";
+        while (current != null) {
+            boolean isActive = current.from() <= toOpId;
+            int opId = isActive ? current.from() : toOpId;
+
+            if (GraalOptions.TraceLinearScanLevel >= 2 && !TTY.isSuppressed()) {
+                if (currentPosition < opId) {
+                    TTY.println();
+                    TTY.println("walkTo(%d) *", opId);
+                }
+            }
+
+            // set currentPosition prior to call of walkTo
+            currentPosition = opId;
+
+            // call walkTo even if currentPosition == id
+            walkTo(State.Active, opId);
+            walkTo(State.Inactive, opId);
+
+            if (isActive) {
+                current.state = State.Active;
+                if (activateCurrent()) {
+                    activeLists.addToListSortedByCurrentFromPositions(currentBinding, current);
+                    intervalMoved(current, currentBinding, State.Unhandled, State.Active);
+                }
+
+                nextInterval();
+            } else {
+                return;
+            }
+        }
+    }
+
+    private void intervalMoved(Interval interval, RegisterBinding kind, State from, State to) {
+        // intervalMoved() is called whenever an interval moves from one interval list to another.
+        // In the implementation of this method it is prohibited to move the interval to any list.
+        if (GraalOptions.TraceLinearScanLevel >= 4 && !TTY.isSuppressed()) {
+            TTY.print(from.toString() + " to " + to.toString());
+            TTY.fillTo(23);
+            TTY.out().println(interval.logString(allocator));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LIRInsertionBuffer.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.alloc;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.lir.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.sun.cri.ci.*;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public final class LIRInsertionBuffer {
+
+    private LIRList lir; // the lir list where ops of this buffer should be inserted later (null when uninitialized)
+
+    // list of insertion points. index and count are stored alternately:
+    // indexAndCount[i * 2]: the index into lir list where "count" ops should be inserted
+    // indexAndCount[i * 2 + 1]: the number of ops to be inserted at index
+    private final IntList indexAndCount;
+
+    // the LIROps to be inserted
+    private final List<LIRInstruction> ops;
+
+    private void appendNew(int index, int count) {
+        indexAndCount.add(index);
+        indexAndCount.add(count);
+    }
+
+    private void setCountAt(int i, int value) {
+        indexAndCount.set((i << 1) + 1, value);
+    }
+
+    LIRInsertionBuffer() {
+        ops = new ArrayList<LIRInstruction>(8);
+        indexAndCount = new IntList(8);
+    }
+
+    // must be called before using the insertion buffer
+    void init(LIRList lir) {
+        assert !initialized() : "already initialized";
+        this.lir = lir;
+        indexAndCount.clear();
+        ops.clear();
+    }
+
+    boolean initialized() {
+        return lir != null;
+    }
+
+    // called automatically when the buffer is appended to the LIRList
+    public void finish() {
+        lir = null;
+    }
+
+    // accessors
+    public LIRList lirList() {
+        return lir;
+    }
+
+    public int numberOfInsertionPoints() {
+        return indexAndCount.size() >> 1;
+    }
+
+    public int indexAt(int i) {
+        return indexAndCount.get((i << 1));
+    }
+
+    public int countAt(int i) {
+        return indexAndCount.get((i << 1) + 1);
+    }
+
+    public int numberOfOps() {
+        return ops.size();
+    }
+
+    public LIRInstruction opAt(int i) {
+        return ops.get(i);
+    }
+
+    void move(int index, CiValue src, CiValue dst, LIRDebugInfo info) {
+        append(index, new LIROp1(LIROpcode.Move, src, dst, dst.kind, info));
+    }
+
+    // Implementation of LIRInsertionBuffer
+
+    private void append(int index, LIRInstruction op) {
+        assert indexAndCount.size() % 2 == 0 : "must have a count for each index";
+
+        int i = numberOfInsertionPoints() - 1;
+        if (i < 0 || indexAt(i) < index) {
+            appendNew(index, 1);
+        } else {
+            assert indexAt(i) == index : "can append LIROps in ascending order only";
+            assert countAt(i) > 0 : "check";
+            setCountAt(i, countAt(i) + 1);
+        }
+        ops.add(op);
+
+        assert verify();
+    }
+
+    private boolean verify() {
+        int sum = 0;
+        int prevIdx = -1;
+
+        for (int i = 0; i < numberOfInsertionPoints(); i++) {
+            assert prevIdx < indexAt(i) : "index must be ordered ascending";
+            sum += countAt(i);
+        }
+        assert sum == numberOfOps() : "wrong total sum";
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,2420 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.alloc;
+
+import static com.sun.cri.ci.CiUtil.*;
+import static java.lang.reflect.Modifier.*;
+
+import java.util.*;
+import java.util.Map.Entry;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.alloc.Interval.RegisterBinding;
+import com.oracle.max.graal.compiler.alloc.Interval.RegisterPriority;
+import com.oracle.max.graal.compiler.alloc.Interval.SpillState;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.compiler.graph.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.lir.*;
+import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode;
+import com.oracle.max.graal.compiler.observer.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.compiler.value.*;
+import com.oracle.max.graal.compiler.value.FrameState.ValueProcedure;
+import com.oracle.max.graal.extensions.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * An implementation of the linear scan register allocator algorithm described
+ * in <a href="http://doi.acm.org/10.1145/1064979.1064998">"Optimized Interval Splitting in a Linear Scan Register Allocator"</a>
+ * by Christian Wimmer and Hanspeter Moessenboeck.
+ *
+ * @author Christian Wimmer (original HotSpot implementation)
+ * @author Thomas Wuerthinger
+ * @author Doug Simon
+ */
+public final class LinearScan {
+
+    final GraalCompilation compilation;
+    final IR ir;
+    final LIRGenerator gen;
+    final FrameMap frameMap;
+    final RiRegisterAttributes[] registerAttributes;
+    final CiRegister[] registers;
+
+    private static final int INITIAL_SPLIT_INTERVALS_CAPACITY = 32;
+
+    /**
+     * List of blocks in linear-scan order. This is only correct as long as the CFG does not change.
+     */
+    final LIRBlock[] sortedBlocks;
+
+    final OperandPool operands;
+
+    /**
+     * Number of stack slots used for intervals allocated to memory.
+     */
+    int maxSpills;
+
+    /**
+     * Unused spill slot for a single-word value because of alignment of a double-word value.
+     */
+    CiStackSlot unusedSpillSlot;
+
+    /**
+     * Map from {@linkplain #operandNumber(CiValue) operand numbers} to intervals.
+     */
+    Interval[] intervals;
+
+    /**
+     * The number of valid entries in {@link #intervals}.
+     */
+    int intervalsSize;
+
+    /**
+     * The index of the first entry in {@link #intervals} for a {@linkplain #createDerivedInterval(Interval) derived interval}.
+     */
+    int firstDerivedIntervalIndex = -1;
+
+    /**
+     * Intervals sorted by {@link Interval#from()}.
+     */
+    Interval[] sortedIntervals;
+
+    /**
+     * Map from an instruction {@linkplain LIRInstruction#id id} to the instruction.
+     * Entries should be retrieved with {@link #instructionForId(int)} as the id is
+     * not simply an index into this array.
+     */
+    LIRInstruction[] opIdToInstructionMap;
+
+    /**
+     * Map from an instruction {@linkplain LIRInstruction#id id} to the {@linkplain
+     * LIRBlock block} containing the instruction. Entries should be retrieved with
+     * {@link #blockForId(int)} as the id is not simply an index into this array.
+     */
+    LIRBlock[] opIdToBlockMap;
+
+    /**
+     * Bit set for each variable that is contained in each loop.
+     */
+    BitMap2D intervalInLoop;
+
+    public LinearScan(GraalCompilation compilation, IR ir, LIRGenerator gen, FrameMap frameMap) {
+        this.compilation = compilation;
+        this.ir = ir;
+        this.gen = gen;
+        this.frameMap = frameMap;
+        this.maxSpills = frameMap.initialSpillSlot();
+        this.unusedSpillSlot = null;
+        this.sortedBlocks = ir.linearScanOrder().toArray(new LIRBlock[ir.linearScanOrder().size()]);
+        CiRegister[] allocatableRegisters = compilation.registerConfig.getAllocatableRegisters();
+        this.registers = new CiRegister[CiRegister.maxRegisterNumber(allocatableRegisters) + 1];
+        for (CiRegister reg : allocatableRegisters) {
+            registers[reg.number] = reg;
+        }
+        this.registerAttributes = compilation.registerConfig.getAttributesMap();
+        this.operands = gen.operands;
+    }
+
+    /**
+     * Converts an operand (variable or register) to an index in a flat address space covering all the
+     * {@linkplain CiVariable variables} and {@linkplain CiRegisterValue registers} being processed by this
+     * allocator.
+     */
+    int operandNumber(CiValue operand) {
+        return operands.operandNumber(operand);
+    }
+
+    static final IntervalPredicate IS_PRECOLORED_INTERVAL = new IntervalPredicate() {
+        @Override
+        public boolean apply(Interval i) {
+            return i.operand.isRegister();
+        }
+    };
+
+    static final IntervalPredicate IS_VARIABLE_INTERVAL = new IntervalPredicate() {
+        @Override
+        public boolean apply(Interval i) {
+            return i.operand.isVariable();
+        }
+    };
+
+    static final IntervalPredicate IS_OOP_INTERVAL = new IntervalPredicate() {
+        @Override
+        public boolean apply(Interval i) {
+            return !i.operand.isRegister() && i.kind() == CiKind.Object;
+        }
+    };
+
+    /**
+     * Gets an object describing the attributes of a given register according to this register configuration.
+     */
+    RiRegisterAttributes attributes(CiRegister reg) {
+        return registerAttributes[reg.number];
+    }
+
+    /**
+     * Allocates the next available spill slot for a value of a given kind.
+     */
+    CiStackSlot allocateSpillSlot(CiKind kind) {
+        CiStackSlot spillSlot;
+        if (numberOfSpillSlots(kind) == 2) {
+            if (isOdd(maxSpills)) {
+                // alignment of double-slot values
+                // the hole because of the alignment is filled with the next single-slot value
+                assert unusedSpillSlot == null : "wasting a spill slot";
+                unusedSpillSlot = CiStackSlot.get(kind, maxSpills);
+                maxSpills++;
+            }
+            spillSlot = CiStackSlot.get(kind, maxSpills);
+            maxSpills += 2;
+        } else if (unusedSpillSlot != null) {
+            // re-use hole that was the result of a previous double-word alignment
+            spillSlot = unusedSpillSlot;
+            unusedSpillSlot = null;
+        } else {
+            spillSlot = CiStackSlot.get(kind, maxSpills);
+            maxSpills++;
+        }
+
+        return spillSlot;
+    }
+
+    void assignSpillSlot(Interval interval) {
+        // assign the canonical spill slot of the parent (if a part of the interval
+        // is already spilled) or allocate a new spill slot
+        if (interval.spillSlot() != null) {
+            interval.assignLocation(interval.spillSlot());
+        } else {
+            CiStackSlot slot = allocateSpillSlot(interval.kind());
+            interval.setSpillSlot(slot);
+            interval.assignLocation(slot);
+        }
+    }
+
+    /**
+     * Creates a new interval.
+     *
+     * @param operand the operand for the interval
+     * @return the created interval
+     */
+    Interval createInterval(CiValue operand) {
+        assert isProcessed(operand);
+        assert operand.isLegal();
+        int operandNumber = operandNumber(operand);
+        Interval interval = new Interval(operand, operandNumber);
+        assert operandNumber < intervalsSize;
+        assert intervals[operandNumber] == null;
+        intervals[operandNumber] = interval;
+        return interval;
+    }
+
+    /**
+     * Creates an interval as a result of splitting or spilling another interval.
+     *
+     * @param source an interval being split of spilled
+     * @return a new interval derived from {@code source}
+     */
+    Interval createDerivedInterval(Interval source) {
+        if (firstDerivedIntervalIndex == -1) {
+            firstDerivedIntervalIndex = intervalsSize;
+        }
+        if (intervalsSize == intervals.length) {
+            intervals = Arrays.copyOf(intervals, intervals.length * 2);
+        }
+        intervalsSize++;
+        Interval interval = createInterval(operands.newVariable(source.kind()));
+        assert intervals[intervalsSize - 1] == interval;
+        return interval;
+    }
+
+    // copy the variable flags if an interval is split
+    void copyRegisterFlags(Interval from, Interval to) {
+        if (operands.mustBeByteRegister(from.operand)) {
+            operands.setMustBeByteRegister((CiVariable) to.operand);
+        }
+
+        // Note: do not copy the mustStartInMemory flag because it is not necessary for child
+        // intervals (only the very beginning of the interval must be in memory)
+    }
+
+    // access to block list (sorted in linear scan order)
+    int blockCount() {
+        assert sortedBlocks.length == ir.linearScanOrder().size() : "invalid cached block list";
+        return sortedBlocks.length;
+    }
+
+    LIRBlock blockAt(int index) {
+        assert sortedBlocks[index] == ir.linearScanOrder().get(index) : "invalid cached block list";
+        return sortedBlocks[index];
+    }
+
+    /**
+     * Gets the size of the {@link LIRBlock#liveIn} and {@link LIRBlock#liveOut} sets for a basic block. These sets do
+     * not include any operands allocated as a result of creating {@linkplain #createDerivedInterval(Interval) derived
+     * intervals}.
+     */
+    int liveSetSize() {
+        return firstDerivedIntervalIndex == -1 ? operands.size() : firstDerivedIntervalIndex;
+    }
+
+    int numLoops() {
+        return ir.numLoops();
+    }
+
+    boolean isIntervalInLoop(int interval, int loop) {
+        return intervalInLoop.at(interval, loop);
+    }
+
+    Interval intervalFor(CiValue operand) {
+        int operandNumber = operandNumber(operand);
+        assert operandNumber < intervalsSize;
+        return intervals[operandNumber];
+    }
+
+    /**
+     * Gets the highest instruction id allocated by this object.
+     */
+    int maxOpId() {
+        assert opIdToInstructionMap.length > 0 : "no operations";
+        return (opIdToInstructionMap.length - 1) << 1;
+    }
+
+    /**
+     * Converts an {@linkplain LIRInstruction#id instruction id} to an instruction index.
+     * All LIR instructions in a method have an index one greater than their linear-scan order predecesor
+     * with the first instruction having an index of 0.
+     */
+    static int opIdToIndex(int opId) {
+        return opId >> 1;
+    }
+
+    /**
+     * Retrieves the {@link LIRInstruction} based on its {@linkplain LIRInstruction#id id}.
+     *
+     * @param opId an instruction {@linkplain LIRInstruction#id id}
+     * @return the instruction whose {@linkplain LIRInstruction#id} {@code == id}
+     */
+    LIRInstruction instructionForId(int opId) {
+        assert isEven(opId) : "opId not even";
+        LIRInstruction instr = opIdToInstructionMap[opIdToIndex(opId)];
+        assert instr.id() == opId;
+        return instr;
+    }
+
+    /**
+     * Gets the block containing a given instruction.
+     *
+     * @param opId an instruction {@linkplain LIRInstruction#id id}
+     * @return the block containing the instruction denoted by {@code opId}
+     */
+    LIRBlock blockForId(int opId) {
+        assert opIdToBlockMap.length > 0 && opId >= 0 && opId <= maxOpId() + 1 : "opId out of range";
+        return opIdToBlockMap[opIdToIndex(opId)];
+    }
+
+    boolean isBlockBegin(int opId) {
+        return opId == 0 || blockForId(opId) != blockForId(opId - 1);
+    }
+
+    boolean coversBlockBegin(int opId1, int opId2) {
+        return blockForId(opId1) != blockForId(opId2);
+    }
+
+    /**
+     * Determines if an {@link LIRInstruction} destroys all caller saved registers.
+     *
+     * @param opId an instruction {@linkplain LIRInstruction#id id}
+     * @return {@code true} if the instruction denoted by {@code id} destroys all caller saved registers.
+     */
+    boolean hasCall(int opId) {
+        assert isEven(opId) : "opId not even";
+        return instructionForId(opId).hasCall;
+    }
+
+    /**
+     * Eliminates moves from register to stack if the stack slot is known to be correct.
+     */
+    void changeSpillDefinitionPos(Interval interval, int defPos) {
+        assert interval.isSplitParent() : "can only be called for split parents";
+
+        switch (interval.spillState()) {
+            case NoDefinitionFound:
+                assert interval.spillDefinitionPos() == -1 : "must no be set before";
+                interval.setSpillDefinitionPos(defPos);
+                interval.setSpillState(SpillState.NoSpillStore);
+                break;
+
+            case NoSpillStore:
+                assert defPos <= interval.spillDefinitionPos() : "positions are processed in reverse order when intervals are created";
+                if (defPos < interval.spillDefinitionPos() - 2 || instructionForId(interval.spillDefinitionPos()).code == LIROpcode.Xir) {
+                    // second definition found, so no spill optimization possible for this interval
+                    interval.setSpillState(SpillState.NoOptimization);
+                } else {
+                    // two consecutive definitions (because of two-operand LIR form)
+                    assert blockForId(defPos) == blockForId(interval.spillDefinitionPos()) : "block must be equal";
+                }
+                break;
+
+            case NoOptimization:
+                // nothing to do
+                break;
+
+            default:
+                throw new CiBailout("other states not allowed at this time");
+        }
+    }
+
+    // called during register allocation
+    void changeSpillState(Interval interval, int spillPos) {
+        switch (interval.spillState()) {
+            case NoSpillStore: {
+                int defLoopDepth = blockForId(interval.spillDefinitionPos()).loopDepth();
+                int spillLoopDepth = blockForId(spillPos).loopDepth();
+
+                if (defLoopDepth < spillLoopDepth) {
+                    // the loop depth of the spilling position is higher then the loop depth
+                    // at the definition of the interval . move write to memory out of loop
+                    // by storing at definitin of the interval
+                    interval.setSpillState(SpillState.StoreAtDefinition);
+                } else {
+                    // the interval is currently spilled only once, so for now there is no
+                    // reason to store the interval at the definition
+                    interval.setSpillState(SpillState.OneSpillStore);
+                }
+                break;
+            }
+
+            case OneSpillStore: {
+                // the interval is spilled more then once, so it is better to store it to
+                // memory at the definition
+                interval.setSpillState(SpillState.StoreAtDefinition);
+                break;
+            }
+
+            case StoreAtDefinition:
+            case StartInMemory:
+            case NoOptimization:
+            case NoDefinitionFound:
+                // nothing to do
+                break;
+
+            default:
+                throw new CiBailout("other states not allowed at this time");
+        }
+    }
+
+    abstract static class IntervalPredicate {
+        abstract boolean apply(Interval i);
+    }
+
+    private static final IntervalPredicate mustStoreAtDefinition = new IntervalPredicate() {
+        @Override
+        public boolean apply(Interval i) {
+            return i.isSplitParent() && i.spillState() == SpillState.StoreAtDefinition;
+        }
+    };
+
+    // called once before assignment of register numbers
+    void eliminateSpillMoves() {
+        if (GraalOptions.TraceLinearScanLevel >= 3) {
+            TTY.println(" Eliminating unnecessary spill moves");
+        }
+
+        // collect all intervals that must be stored after their definition.
+        // the list is sorted by Interval.spillDefinitionPos
+        Interval interval;
+        interval = createUnhandledLists(mustStoreAtDefinition, null).first;
+        if (GraalOptions.DetailedAsserts) {
+            checkIntervals(interval);
+        }
+
+        LIRInsertionBuffer insertionBuffer = new LIRInsertionBuffer();
+        int numBlocks = blockCount();
+        for (int i = 0; i < numBlocks; i++) {
+            LIRBlock block = blockAt(i);
+            List<LIRInstruction> instructions = block.lir().instructionsList();
+            int numInst = instructions.size();
+            boolean hasNew = false;
+
+            // iterate all instructions of the block. skip the first because it is always a label
+            for (int j = 1; j < numInst; j++) {
+                LIRInstruction op = instructions.get(j);
+                int opId = op.id();
+
+                if (opId == -1) {
+                    CiValue resultOperand = op.result();
+                    // remove move from register to stack if the stack slot is guaranteed to be correct.
+                    // only moves that have been inserted by LinearScan can be removed.
+                    assert op.code == LIROpcode.Move : "only moves can have a opId of -1";
+                    assert resultOperand.isVariable() : "LinearScan inserts only moves to variables";
+
+                    LIROp1 op1 = (LIROp1) op;
+                    Interval curInterval = intervalFor(resultOperand);
+
+                    if (!curInterval.location().isRegister() && curInterval.alwaysInMemory()) {
+                        // move target is a stack slot that is always correct, so eliminate instruction
+                        if (GraalOptions.TraceLinearScanLevel >= 4) {
+                            TTY.println("eliminating move from interval %d to %d", operandNumber(op1.operand()), operandNumber(op1.result()));
+                        }
+                        instructions.set(j, null); // null-instructions are deleted by assignRegNum
+                    }
+
+                } else {
+                    // insert move from register to stack just after the beginning of the interval
+                    assert interval == Interval.EndMarker || interval.spillDefinitionPos() >= opId : "invalid order";
+                    assert interval == Interval.EndMarker || (interval.isSplitParent() && interval.spillState() == SpillState.StoreAtDefinition) : "invalid interval";
+
+                    while (interval != Interval.EndMarker && interval.spillDefinitionPos() == opId) {
+                        if (!hasNew) {
+                            // prepare insertion buffer (appended when all instructions of the block are processed)
+                            insertionBuffer.init(block.lir());
+                            hasNew = true;
+                        }
+
+                        CiValue fromLocation = interval.location();
+                        CiValue toLocation = canonicalSpillOpr(interval);
+
+                        assert fromLocation.isRegister() : "from operand must be a register but is: " + fromLocation + " toLocation=" + toLocation + " spillState=" + interval.spillState();
+                        assert toLocation.isStackSlot() : "to operand must be a stack slot";
+
+                        insertionBuffer.move(j, fromLocation, toLocation, null);
+
+                        if (GraalOptions.TraceLinearScanLevel >= 4) {
+                            CiStackSlot slot = interval.spillSlot();
+                            TTY.println("inserting move after definition of interval %d to stack slot %d%s at opId %d",
+                                            interval.operandNumber, slot.index(), slot.inCallerFrame() ? " in caller frame" : "", opId);
+                        }
+
+                        interval = interval.next;
+                    }
+                }
+            } // end of instruction iteration
+
+            if (hasNew) {
+                block.lir().append(insertionBuffer);
+            }
+        } // end of block iteration
+
+        assert interval == Interval.EndMarker : "missed an interval";
+    }
+
+    private void checkIntervals(Interval interval) {
+        Interval prev = null;
+        Interval temp = interval;
+        while (temp != Interval.EndMarker) {
+            assert temp.spillDefinitionPos() > 0 : "invalid spill definition pos";
+            if (prev != null) {
+                assert temp.from() >= prev.from() : "intervals not sorted";
+                assert temp.spillDefinitionPos() >= prev.spillDefinitionPos() : "when intervals are sorted by from :  then they must also be sorted by spillDefinitionPos";
+            }
+
+            assert temp.spillSlot() != null : "interval has no spill slot assigned";
+            assert temp.spillDefinitionPos() >= temp.from() : "invalid order";
+            assert temp.spillDefinitionPos() <= temp.from() + 2 : "only intervals defined once at their start-pos can be optimized";
+
+            if (GraalOptions.TraceLinearScanLevel >= 4) {
+                TTY.println("interval %d (from %d to %d) must be stored at %d", temp.operandNumber, temp.from(), temp.to(), temp.spillDefinitionPos());
+            }
+
+            prev = temp;
+            temp = temp.next;
+        }
+    }
+
+    /**
+     * Numbers all instructions in all blocks. The numbering follows the {@linkplain ComputeLinearScanOrder linear scan order}.
+     */
+    void numberInstructions() {
+        // Assign IDs to LIR nodes and build a mapping, lirOps, from ID to LIRInstruction node.
+        int numBlocks = blockCount();
+        int numInstructions = 0;
+        for (int i = 0; i < numBlocks; i++) {
+            numInstructions += blockAt(i).lir().instructionsList().size();
+        }
+
+        // initialize with correct length
+        opIdToInstructionMap = new LIRInstruction[numInstructions];
+        opIdToBlockMap = new LIRBlock[numInstructions];
+
+        int opId = 0;
+        int index = 0;
+
+        for (int i = 0; i < numBlocks; i++) {
+            LIRBlock block = blockAt(i);
+            block.setFirstLirInstructionId(opId);
+            List<LIRInstruction> instructions = block.lir().instructionsList();
+
+            int numInst = instructions.size();
+            for (int j = 0; j < numInst; j++) {
+                LIRInstruction op = instructions.get(j);
+                op.setId(opId);
+
+                opIdToInstructionMap[index] = op;
+                opIdToBlockMap[index] = block;
+                assert instructionForId(opId) == op : "must match";
+
+                index++;
+                opId += 2; // numbering of lirOps by two
+            }
+            block.setLastLirInstructionId((opId - 2));
+        }
+        assert index == numInstructions : "must match";
+        assert (index << 1) == opId : "must match: " + (index << 1);
+    }
+
+    /**
+     * Computes local live sets (i.e. {@link LIRBlock#liveGen} and {@link LIRBlock#liveKill}) separately for each block.
+     */
+    void computeLocalLiveSets() {
+        int numBlocks = blockCount();
+        int liveSize = liveSetSize();
+
+        BitMap2D localIntervalInLoop = new BitMap2D(operands.size(), numLoops());
+
+        // iterate all blocks
+        for (int i = 0; i < numBlocks; i++) {
+            LIRBlock block = blockAt(i);
+            final BitMap liveGen = new BitMap(liveSize);
+            final BitMap liveKill = new BitMap(liveSize);
+
+            List<LIRInstruction> instructions = block.lir().instructionsList();
+            int numInst = instructions.size();
+
+            // iterate all instructions of the block. skip the first because it is always a label
+            assert !instructions.get(0).hasOperands() : "first operation must always be a label";
+            for (int j = 1; j < numInst; j++) {
+                final LIRInstruction op = instructions.get(j);
+
+                // iterate input operands of instruction
+                int n = op.operandCount(LIRInstruction.OperandMode.Input);
+                for (int k = 0; k < n; k++) {
+                    CiValue operand = op.operandAt(LIRInstruction.OperandMode.Input, k);
+
+                    if (operand.isVariable()) {
+                        int operandNum = operandNumber(operand);
+                        if (!liveKill.get(operandNum)) {
+                            liveGen.set(operandNum);
+                            if (GraalOptions.TraceLinearScanLevel >= 4) {
+                                TTY.println("  Setting liveGen for operand %d at instruction %d", operandNum, op.id());
+                            }
+                        }
+                        if (block.loopIndex() >= 0) {
+                            localIntervalInLoop.setBit(operandNum, block.loopIndex());
+                        }
+                    }
+
+                    if (GraalOptions.DetailedAsserts) {
+                        assert operand.isVariableOrRegister() : "visitor should only return register operands";
+                        verifyInput(block, liveKill, operand);
+                    }
+                }
+
+                // Add uses of live locals from interpreter's point of view for proper debug information generation
+                LIRDebugInfo info = op.info;
+                if (info != null) {
+                    assert info.state != null;
+                    info.state.forEachLiveStateValue(new ValueProcedure() {
+                        public void doValue(Value value) {
+                            CiValue operand = value.operand();
+                            if (operand.isVariable()) {
+                                int operandNum = operandNumber(operand);
+                                if (!liveKill.get(operandNum)) {
+                                    liveGen.set(operandNum);
+                                    if (GraalOptions.TraceLinearScanLevel >= 4) {
+                                        TTY.println("  Setting liveGen for value %s, LIR opId %d, operand %d because of state for %s", Util.valueString(value), op.id(), operandNum, op);
+                                    }
+                                }
+                            } else if (operand.isRegister()) {
+                                assert !isProcessed(operand) && !operand.kind.isObject();
+                            } else {
+                                assert operand.isConstant() || operand.isIllegal() : "invalid operand for deoptimization value: " + value;
+                            }
+                        }
+                    });
+                }
+
+                // iterate temp operands of instruction
+                n = op.operandCount(LIRInstruction.OperandMode.Temp);
+                for (int k = 0; k < n; k++) {
+                    CiValue operand = op.operandAt(LIRInstruction.OperandMode.Temp, k);
+
+                    if (operand.isVariable()) {
+                        int varNum = operandNumber(operand);
+                        liveKill.set(varNum);
+                        if (block.loopIndex() >= 0) {
+                            localIntervalInLoop.setBit(varNum, block.loopIndex());
+                        }
+                    }
+
+                    if (GraalOptions.DetailedAsserts) {
+                        assert operand.isVariableOrRegister() : "visitor should only return register operands";
+                        verifyTemp(liveKill, operand);
+                    }
+                }
+
+                // iterate output operands of instruction
+                n = op.operandCount(LIRInstruction.OperandMode.Output);
+                for (int k = 0; k < n; k++) {
+                    CiValue operand = op.operandAt(LIRInstruction.OperandMode.Output, k);
+
+                    if (operand.isVariable()) {
+                        int varNum = operandNumber(operand);
+                        liveKill.set(varNum);
+                        if (block.loopIndex() >= 0) {
+                            localIntervalInLoop.setBit(varNum, block.loopIndex());
+                        }
+                    }
+
+                    if (GraalOptions.DetailedAsserts) {
+                        assert operand.isVariableOrRegister() : "visitor should only return register operands";
+                        // fixed intervals are never live at block boundaries, so
+                        // they need not be processed in live sets
+                        // process them only in debug mode so that this can be checked
+                        verifyTemp(liveKill, operand);
+                    }
+                }
+            } // end of instruction iteration
+
+            block.liveGen = liveGen;
+            block.liveKill = liveKill;
+            block.liveIn = new BitMap(liveSize);
+            block.liveOut = new BitMap(liveSize);
+
+            if (GraalOptions.TraceLinearScanLevel >= 4) {
+                TTY.println("liveGen  B%d %s", block.blockID(), block.liveGen);
+                TTY.println("liveKill B%d %s", block.blockID(), block.liveKill);
+            }
+        } // end of block iteration
+
+        intervalInLoop = localIntervalInLoop;
+    }
+
+    private void verifyTemp(BitMap liveKill, CiValue operand) {
+        // fixed intervals are never live at block boundaries, so
+        // they need not be processed in live sets
+        // process them only in debug mode so that this can be checked
+        if (!operand.isVariable()) {
+            if (isProcessed(operand)) {
+                liveKill.set(operandNumber(operand));
+            }
+        }
+    }
+
+    private void verifyInput(LIRBlock block, BitMap liveKill, CiValue operand) {
+        // fixed intervals are never live at block boundaries, so
+        // they need not be processed in live sets.
+        // this is checked by these assertions to be sure about it.
+        // the entry block may have incoming
+        // values in registers, which is ok.
+        if (!operand.isVariable() && block != ir.startBlock) {
+            if (isProcessed(operand)) {
+                assert liveKill.get(operandNumber(operand)) : "using fixed register that is not defined in this block";
+            }
+        }
+    }
+
+    /**
+     * Performs a backward dataflow analysis to compute global live sets (i.e. {@link LIRBlock#liveIn} and
+     * {@link LIRBlock#liveOut}) for each block.
+     */
+    void computeGlobalLiveSets() {
+        int numBlocks = blockCount();
+        boolean changeOccurred;
+        boolean changeOccurredInBlock;
+        int iterationCount = 0;
+        BitMap liveOut = new BitMap(liveSetSize()); // scratch set for calculations
+
+        // Perform a backward dataflow analysis to compute liveOut and liveIn for each block.
+        // The loop is executed until a fixpoint is reached (no changes in an iteration)
+        do {
+            changeOccurred = false;
+
+            // iterate all blocks in reverse order
+            for (int i = numBlocks - 1; i >= 0; i--) {
+                LIRBlock block = blockAt(i);
+
+                changeOccurredInBlock = false;
+
+                // liveOut(block) is the union of liveIn(sux), for successors sux of block
+                int n = block.numberOfSux();
+                if (n > 0) {
+                    // block has successors
+                    if (n > 0) {
+                        liveOut.setFrom(block.suxAt(0).liveIn);
+                        for (int j = 1; j < n; j++) {
+                            liveOut.setUnion(block.suxAt(j).liveIn);
+                        }
+                    } else {
+                        liveOut.clearAll();
+                    }
+
+                    if (!block.liveOut.isSame(liveOut)) {
+                        // A change occurred. Swap the old and new live out sets to avoid copying.
+                        BitMap temp = block.liveOut;
+                        block.liveOut = liveOut;
+                        liveOut = temp;
+
+                        changeOccurred = true;
+                        changeOccurredInBlock = true;
+                    }
+                }
+
+                if (iterationCount == 0 || changeOccurredInBlock) {
+                    // liveIn(block) is the union of liveGen(block) with (liveOut(block) & !liveKill(block))
+                    // note: liveIn has to be computed only in first iteration or if liveOut has changed!
+                    BitMap liveIn = block.liveIn;
+                    liveIn.setFrom(block.liveOut);
+                    liveIn.setDifference(block.liveKill);
+                    liveIn.setUnion(block.liveGen);
+                }
+
+                if (GraalOptions.TraceLinearScanLevel >= 4) {
+                    traceLiveness(changeOccurredInBlock, iterationCount, block);
+                }
+            }
+            iterationCount++;
+
+            if (changeOccurred && iterationCount > 50) {
+                throw new CiBailout("too many iterations in computeGlobalLiveSets");
+            }
+        } while (changeOccurred);
+
+        if (GraalOptions.DetailedAsserts) {
+            verifyLiveness(numBlocks);
+        }
+
+        // check that the liveIn set of the first block is empty
+        LIRBlock startBlock = ir.startBlock;
+        BitMap liveInArgs = new BitMap(startBlock.liveIn.size());
+        if (!startBlock.liveIn.isSame(liveInArgs)) {
+            if (GraalOptions.DetailedAsserts) {
+                reportFailure(numBlocks);
+            }
+
+            TTY.println("preds=" + startBlock.blockPredecessors().size() + ", succs=" + startBlock.blockSuccessors().size());
+            TTY.println("startBlock-ID: " + startBlock.blockID());
+
+            // bailout of if this occurs in product mode.
+            throw new CiBailout("liveIn set of first block must be empty");
+        }
+    }
+
+    private void reportFailure(int numBlocks) {
+        TTY.println(compilation.method.toString());
+        TTY.println("Error: liveIn set of first block must be empty (when this fails, variables are used before they are defined)");
+        TTY.print("affected registers:");
+        TTY.println(ir.startBlock.liveIn.toString());
+
+        // print some additional information to simplify debugging
+        for (int operandNum = 0; operandNum < ir.startBlock.liveIn.size(); operandNum++) {
+            if (ir.startBlock.liveIn.get(operandNum)) {
+                CiValue operand = operands.operandFor(operandNum);
+                Value instr = operand.isVariable() ? gen.operands.instructionForResult(((CiVariable) operand)) : null;
+                TTY.println(" var %d (HIR instruction %s)", operandNum, instr == null ? " " : instr.toString());
+
+                if (instr instanceof Phi) {
+                    Phi phi = (Phi) instr;
+                    TTY.println("phi block begin: " + phi.merge());
+                    TTY.println("pred count on blockbegin: " + phi.merge().phiPredecessorCount());
+                    TTY.println("phi values: " + phi.valueCount());
+                    TTY.println("phi block preds:");
+                    for (Node n : phi.merge().phiPredecessors()) {
+                        TTY.println(n.toString());
+                    }
+                }
+
+                for (int j = 0; j < numBlocks; j++) {
+                    LIRBlock block = blockAt(j);
+                    if (block.liveGen.get(operandNum)) {
+                        TTY.println("  used in block B%d", block.blockID());
+                        for (LIRInstruction ins : block.lir().instructionsList()) {
+                            TTY.println(ins.id() + ": " + ins.result() + " " + ins.toString());
+                        }
+                    }
+                    if (block.liveKill.get(operandNum)) {
+                        TTY.println("  defined in block B%d", block.blockID());
+                        for (LIRInstruction ins : block.lir().instructionsList()) {
+                            TTY.println(ins.id() + ": " + ins.result() + " " + ins.toString());
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private void verifyLiveness(int numBlocks) {
+        // check that fixed intervals are not live at block boundaries
+        // (live set must be empty at fixed intervals)
+        for (int i = 0; i < numBlocks; i++) {
+            LIRBlock block = blockAt(i);
+            for (int j = 0; j <= operands.maxRegisterNumber(); j++) {
+                assert !block.liveIn.get(j) : "liveIn  set of fixed register must be empty";
+                assert !block.liveOut.get(j) : "liveOut set of fixed register must be empty";
+                assert !block.liveGen.get(j) : "liveGen set of fixed register must be empty";
+            }
+        }
+    }
+
+    private void traceLiveness(boolean changeOccurredInBlock, int iterationCount, LIRBlock block) {
+        char c = iterationCount == 0 || changeOccurredInBlock ? '*' : ' ';
+        TTY.print("(%d) liveIn%c  B%d ", iterationCount, c, block.blockID());
+        TTY.println(block.liveIn.toString());
+        TTY.print("(%d) liveOut%c B%d ", iterationCount, c, block.blockID());
+        TTY.println(block.liveOut.toString());
+    }
+
+    Interval addUse(CiValue operand, int from, int to, RegisterPriority registerPriority, CiKind kind) {
+        if (!isProcessed(operand)) {
+            return null;
+        }
+        if (GraalOptions.TraceLinearScanLevel >= 2 && kind == null) {
+            TTY.println(" use %s from %d to %d (%s)", operand, from, to, registerPriority.name());
+        }
+
+        if (kind == null) {
+            kind = operand.kind.stackKind();
+        }
+        Interval interval = intervalFor(operand);
+        if (interval == null) {
+            interval = createInterval(operand);
+        }
+
+        if (kind != CiKind.Illegal) {
+            interval.setKind(kind);
+        }
+
+        if (operand.isVariable() && gen.operands.mustStayInMemory((CiVariable) operand)) {
+            interval.addRange(from, maxOpId());
+        } else {
+            interval.addRange(from, to);
+        }
+
+        interval.addUsePos(to, registerPriority);
+        return interval;
+    }
+
+    void addTemp(CiValue operand, int tempPos, RegisterPriority registerPriority, CiKind kind) {
+        if (!isProcessed(operand)) {
+            return;
+        }
+        Interval interval = intervalFor(operand);
+        if (interval == null) {
+            interval = createInterval(operand);
+        }
+
+        if (kind != CiKind.Illegal) {
+            interval.setKind(kind);
+        }
+
+        interval.addRange(tempPos, tempPos + 1);
+        interval.addUsePos(tempPos, registerPriority);
+    }
+
+    boolean isProcessed(CiValue operand) {
+        return !operand.isRegister() || attributes(operand.asRegister()).isAllocatable;
+    }
+
+    void addDef(CiValue operand, int defPos, RegisterPriority registerPriority, CiKind kind) {
+        if (!isProcessed(operand)) {
+            return;
+        }
+        if (GraalOptions.TraceLinearScanLevel >= 2) {
+            TTY.println(" def %s defPos %d (%s)", operand, defPos, registerPriority.name());
+        }
+        Interval interval = intervalFor(operand);
+        if (interval != null) {
+
+            if (kind != CiKind.Illegal) {
+                interval.setKind(kind);
+            }
+
+            Range r = interval.first();
+            if (r.from <= defPos) {
+                // Update the starting point (when a range is first created for a use, its
+                // start is the beginning of the current block until a def is encountered.)
+                r.from = defPos;
+                interval.addUsePos(defPos, registerPriority);
+
+            } else {
+                // Dead value - make vacuous interval
+                // also add register priority for dead intervals
+                interval.addRange(defPos, defPos + 1);
+                interval.addUsePos(defPos, registerPriority);
+                if (GraalOptions.TraceLinearScanLevel >= 2) {
+                    TTY.println("Warning: def of operand %s at %d occurs without use", operand, defPos);
+                }
+            }
+
+        } else {
+            // Dead value - make vacuous interval
+            // also add register priority for dead intervals
+            interval = createInterval(operand);
+            if (kind != CiKind.Illegal) {
+                interval.setKind(kind);
+            }
+
+            interval.addRange(defPos, defPos + 1);
+            interval.addUsePos(defPos, registerPriority);
+            if (GraalOptions.TraceLinearScanLevel >= 2) {
+                TTY.println("Warning: dead value %s at %d in live intervals", operand, defPos);
+            }
+        }
+
+        changeSpillDefinitionPos(interval, defPos);
+        if (registerPriority == RegisterPriority.None && interval.spillState().ordinal() <= SpillState.StartInMemory.ordinal()) {
+            // detection of method-parameters and roundfp-results
+            // TODO: move this directly to position where use-kind is computed
+            interval.setSpillState(SpillState.StartInMemory);
+        }
+    }
+
+    /**
+     * Determines the register priority for an instruction's output/result operand.
+     */
+    RegisterPriority registerPriorityOfOutputOperand(LIRInstruction op, CiValue operand) {
+        if (op.code == LIROpcode.Move) {
+            LIROp1 move = (LIROp1) op;
+            CiValue res = move.result();
+            boolean resultInMemory = res.isVariable() && operands.mustStartInMemory((CiVariable) res);
+
+            if (resultInMemory) {
+                // Begin of an interval with mustStartInMemory set.
+                // This interval will always get a stack slot first, so return noUse.
+                return RegisterPriority.None;
+
+            } else if (move.operand().isStackSlot()) {
+                // method argument (condition must be equal to handleMethodArguments)
+                return RegisterPriority.None;
+
+            }
+        }
+
+        if (operand.isVariable() && operands.mustStartInMemory((CiVariable) operand)) {
+            // result is a stack-slot, so prevent immediate reloading
+            return RegisterPriority.None;
+        }
+
+        // all other operands require a register
+        return RegisterPriority.MustHaveRegister;
+    }
+
+    /**
+     * Determines the priority which with an instruction's input operand will be allocated a register.
+     */
+    RegisterPriority registerPriorityOfInputOperand(LIRInstruction op, CiValue operand) {
+        if (op.code == LIROpcode.Move) {
+            LIROp1 move = (LIROp1) op;
+            CiValue res = move.result();
+            boolean resultInMemory = res.isVariable() && operands.mustStartInMemory((CiVariable) res);
+
+            if (resultInMemory) {
+                // Move to an interval with mustStartInMemory set.
+                // To avoid moves from stack to stack (not allowed) force the input operand to a register
+                return RegisterPriority.MustHaveRegister;
+
+            } else if (move.operand().isVariableOrRegister() && move.result().isVariableOrRegister()) {
+                // The input operand is not forced to a register (moves from stack to register are allowed),
+                // but it is faster if the input operand is in a register
+                return RegisterPriority.ShouldHaveRegister;
+            }
+        }
+
+        if (compilation.target.arch.isX86()) {
+            if (op.code == LIROpcode.Cmove) {
+                // conditional moves can handle stack operands
+                assert op.result().isVariableOrRegister();
+                return RegisterPriority.ShouldHaveRegister;
+            }
+
+            // optimizations for second input operand of arithmetic operations on Intel
+            // this operand is allowed to be on the stack in some cases
+            CiKind kind = operand.kind.stackKind();
+            if (kind == CiKind.Float || kind == CiKind.Double) {
+                // SSE float instruction (CiKind.Double only supported with SSE2)
+                switch (op.code) {
+                    case Cmp:
+                    case Add:
+                    case Sub:
+                    case Mul:
+                    case Div: {
+                        LIROp2 op2 = (LIROp2) op;
+                        if (op2.operand1() != op2.operand2() && op2.operand2() == operand) {
+                            assert (op2.result().isVariableOrRegister() || op.code == LIROpcode.Cmp) && op2.operand1().isVariableOrRegister() : "cannot mark second operand as stack if others are not in register";
+                            return RegisterPriority.ShouldHaveRegister;
+                        }
+                    }
+                }
+            } else if (kind != CiKind.Long) {
+                // integer instruction (note: long operands must always be in register)
+                switch (op.code) {
+                    case Cmp:
+                    case Add:
+                    case Sub:
+                    case LogicAnd:
+                    case LogicOr:
+                    case LogicXor: {
+                        LIROp2 op2 = (LIROp2) op;
+                        if (op2.operand1() != op2.operand2() && op2.operand2() == operand) {
+                            assert (op2.result().isVariableOrRegister() || op.code == LIROpcode.Cmp) && op2.operand1().isVariableOrRegister() : "cannot mark second operand as stack if others are not in register";
+                            return RegisterPriority.ShouldHaveRegister;
+                        }
+                    }
+                }
+            }
+        } // X86
+
+        // all other operands require a register
+        return RegisterPriority.MustHaveRegister;
+    }
+
+    /**
+     * Optimizes moves related to incoming stack based arguments.
+     * The interval for the destination of such moves is assigned
+     * the stack slot (which is in the caller's frame) as its
+     * spill slot.
+     */
+    void handleMethodArguments(LIRInstruction op) {
+        if (op.code == LIROpcode.Move) {
+            LIROp1 move = (LIROp1) op;
+
+            if (move.operand().isStackSlot()) {
+                CiStackSlot slot = (CiStackSlot) move.operand();
+                if (GraalOptions.DetailedAsserts) {
+                    int argSlots = compilation.method.signature().argumentSlots(!isStatic(compilation.method.accessFlags()));
+                    assert slot.index() >= 0 && slot.index() < argSlots;
+                    assert move.id() > 0 : "invalid id";
+                    assert blockForId(move.id()).numberOfPreds() == 0 : "move from stack must be in first block";
+                    assert move.result().isVariable() : "result of move must be a variable";
+
+                    if (GraalOptions.TraceLinearScanLevel >= 4) {
+                        TTY.println("found move from stack slot %s to %s", slot, move.result());
+                    }
+                }
+
+                Interval interval = intervalFor(move.result());
+                CiStackSlot copySlot = slot;
+                if (GraalOptions.CopyPointerStackArguments && slot.kind == CiKind.Object) {
+                    copySlot = allocateSpillSlot(slot.kind);
+                }
+                interval.setSpillSlot(copySlot);
+                interval.assignLocation(copySlot);
+            }
+        }
+    }
+
+    void addRegisterHints(LIRInstruction op) {
+        switch (op.code) {
+            case Move: // fall through
+            case Convert: {
+                LIROp1 move = (LIROp1) op;
+
+                CiValue moveFrom = move.operand();
+                CiValue moveTo = move.result();
+
+                if (moveTo.isVariableOrRegister() && moveFrom.isVariableOrRegister()) {
+                    Interval from = intervalFor(moveFrom);
+                    Interval to = intervalFor(moveTo);
+                    if (from != null && to != null) {
+                        to.setLocationHint(from);
+                        if (GraalOptions.TraceLinearScanLevel >= 4) {
+                            TTY.println("operation at opId %d: added hint from interval %d to %d", move.id(), from.operandNumber, to.operandNumber);
+                        }
+                    }
+                }
+                break;
+            }
+            case Cmove: {
+                LIROp2 cmove = (LIROp2) op;
+
+                CiValue moveFrom = cmove.operand1();
+                CiValue moveTo = cmove.result();
+
+                if (moveTo.isVariableOrRegister() && moveFrom.isVariableOrRegister()) {
+                    Interval from = intervalFor(moveFrom);
+                    Interval to = intervalFor(moveTo);
+                    if (from != null && to != null) {
+                        to.setLocationHint(from);
+                        if (GraalOptions.TraceLinearScanLevel >= 4) {
+                            TTY.println("operation at opId %d: added hint from interval %d to %d", cmove.id(), from.operandNumber, to.operandNumber);
+                        }
+                    }
+                }
+                break;
+            }
+        }
+    }
+
+    void buildIntervals() {
+        intervalsSize = operands.size();
+        intervals = new Interval[intervalsSize + INITIAL_SPLIT_INTERVALS_CAPACITY];
+
+        // create a list with all caller-save registers (cpu, fpu, xmm)
+        RiRegisterConfig registerConfig = compilation.registerConfig;
+        CiRegister[] callerSaveRegs = registerConfig.getCallerSaveRegisters();
+
+        // iterate all blocks in reverse order
+        for (int i = blockCount() - 1; i >= 0; i--) {
+            LIRBlock block = blockAt(i);
+            List<LIRInstruction> instructions = block.lir().instructionsList();
+            final int blockFrom = block.firstLirInstructionId();
+            int blockTo = block.lastLirInstructionId();
+
+            assert blockFrom == instructions.get(0).id();
+            assert blockTo == instructions.get(instructions.size() - 1).id();
+
+            // Update intervals for operands live at the end of this block;
+            BitMap live = block.liveOut;
+            for (int operandNum = live.nextSetBit(0); operandNum >= 0; operandNum = live.nextSetBit(operandNum + 1)) {
+                assert live.get(operandNum) : "should not stop here otherwise";
+                CiValue operand = operands.operandFor(operandNum);
+                if (GraalOptions.TraceLinearScanLevel >= 2) {
+                    TTY.println("live in %s to %d", operand, blockTo + 2);
+                }
+
+                addUse(operand, blockFrom, blockTo + 2, RegisterPriority.None, CiKind.Illegal);
+
+                // add special use positions for loop-end blocks when the
+                // interval is used anywhere inside this loop. It's possible
+                // that the block was part of a non-natural loop, so it might
+                // have an invalid loop index.
+                if (block.isLinearScanLoopEnd() && block.loopIndex() != -1 && isIntervalInLoop(operandNum, block.loopIndex())) {
+                    intervalFor(operand).addUsePos(blockTo + 1, RegisterPriority.LiveAtLoopEnd);
+                }
+            }
+
+            // iterate all instructions of the block in reverse order.
+            // skip the first instruction because it is always a label
+            // definitions of intervals are processed before uses
+            assert !instructions.get(0).hasOperands() : "first operation must always be a label";
+            for (int j = instructions.size() - 1; j >= 1; j--) {
+                LIRInstruction op = instructions.get(j);
+                final int opId = op.id();
+
+                // add a temp range for each register if operation destroys caller-save registers
+                if (op.hasCall) {
+                    for (CiRegister r : callerSaveRegs) {
+                        if (attributes(r).isAllocatable) {
+                            addTemp(r.asValue(), opId, RegisterPriority.None, CiKind.Illegal);
+                        }
+                    }
+                    if (GraalOptions.TraceLinearScanLevel >= 4) {
+                        TTY.println("operation destroys all caller-save registers");
+                    }
+                }
+
+                // Add any platform dependent temps
+                pdAddTemps(op);
+
+                // visit definitions (output and temp operands)
+                int k;
+                int n;
+                n = op.operandCount(LIRInstruction.OperandMode.Output);
+                for (k = 0; k < n; k++) {
+                    CiValue operand = op.operandAt(LIRInstruction.OperandMode.Output, k);
+                    assert operand.isVariableOrRegister();
+                    addDef(operand, opId, registerPriorityOfOutputOperand(op, operand), operand.kind.stackKind());
+                }
+
+                n = op.operandCount(LIRInstruction.OperandMode.Temp);
+                for (k = 0; k < n; k++) {
+                    CiValue operand = op.operandAt(LIRInstruction.OperandMode.Temp, k);
+                    assert operand.isVariableOrRegister();
+                    if (GraalOptions.TraceLinearScanLevel >= 2) {
+                        TTY.println(" temp %s tempPos %d (%s)", operand, opId, RegisterPriority.MustHaveRegister.name());
+                    }
+                    addTemp(operand, opId, RegisterPriority.MustHaveRegister, operand.kind.stackKind());
+                }
+
+                // visit uses (input operands)
+                n = op.operandCount(LIRInstruction.OperandMode.Input);
+                for (k = 0; k < n; k++) {
+                    CiValue operand = op.operandAt(LIRInstruction.OperandMode.Input, k);
+                    assert operand.isVariableOrRegister();
+                    RegisterPriority p = registerPriorityOfInputOperand(op, operand);
+                    Interval interval = addUse(operand, blockFrom, opId, p, null);
+                    if (interval != null && op instanceof LIRXirInstruction) {
+                        Range range = interval.first();
+                        // (tw) Increase range by 1 in order to overlap the input with the temp and the output operand.
+                        if (range.to == opId) {
+                            range.to++;
+                        }
+                    }
+                }
+
+                // Add uses of live locals from interpreter's point of view for proper
+                // debug information generation
+                // Treat these operands as temp values (if the live range is extended
+                // to a call site, the value would be in a register at the call otherwise)
+                LIRDebugInfo info = op.info;
+                if (info != null) {
+                    info.state.forEachLiveStateValue(new ValueProcedure() {
+                        public void doValue(Value value) {
+                            CiValue operand = value.operand();
+                            if (operand.isVariableOrRegister()) {
+                                addUse(operand, blockFrom, (opId + 1), RegisterPriority.None, null);
+                            }
+                        }
+                    });
+                }
+
+                // special steps for some instructions (especially moves)
+                handleMethodArguments(op);
+                addRegisterHints(op);
+
+            } // end of instruction iteration
+        } // end of block iteration
+
+        // add the range [0, 1] to all fixed intervals.
+        // the register allocator need not handle unhandled fixed intervals
+        for (Interval interval : intervals) {
+            if (interval != null && interval.operand.isRegister()) {
+                interval.addRange(0, 1);
+            }
+        }
+    }
+
+    // * Phase 5: actual register allocation
+
+    private void pdAddTemps(LIRInstruction op) {
+        // TODO Platform dependent!
+        assert compilation.target.arch.isX86();
+
+        switch (op.code) {
+            case Tan:
+            case Sin:
+            case Cos: {
+                // The slow path for these functions may need to save and
+                // restore all live registers but we don't want to save and
+                // restore everything all the time, so mark the xmms as being
+                // killed. If the slow path were explicit or we could propagate
+                // live register masks down to the assembly we could do better
+                // but we don't have any easy way to do that right now. We
+                // could also consider not killing all xmm registers if we
+                // assume that slow paths are uncommon but it's not clear that
+                // would be a good idea.
+                if (GraalOptions.TraceLinearScanLevel >= 2) {
+                    TTY.println("killing XMMs for trig");
+                }
+                int opId = op.id();
+
+                for (CiRegister r : compilation.registerConfig.getCallerSaveRegisters()) {
+                    if (r.isFpu()) {
+                        addTemp(r.asValue(), opId, RegisterPriority.None, CiKind.Illegal);
+                    }
+                }
+                break;
+            }
+        }
+
+    }
+
+    boolean isSorted(Interval[] intervals) {
+        int from = -1;
+        for (Interval interval : intervals) {
+            assert interval != null;
+            assert from <= interval.from();
+            from = interval.from();
+
+            // XXX: very slow!
+            assert Arrays.asList(this.intervals).contains(interval);
+        }
+        return true;
+    }
+
+    Interval addToList(Interval first, Interval prev, Interval interval) {
+        Interval newFirst = first;
+        if (prev != null) {
+            prev.next = interval;
+        } else {
+            newFirst = interval;
+        }
+        return newFirst;
+    }
+
+    Interval.Pair createUnhandledLists(IntervalPredicate isList1, IntervalPredicate isList2) {
+        assert isSorted(sortedIntervals) : "interval list is not sorted";
+
+        Interval list1 = Interval.EndMarker;
+        Interval list2 = Interval.EndMarker;
+
+        Interval list1Prev = null;
+        Interval list2Prev = null;
+        Interval v;
+
+        int n = sortedIntervals.length;
+        for (int i = 0; i < n; i++) {
+            v = sortedIntervals[i];
+            if (v == null) {
+                continue;
+            }
+
+            if (isList1.apply(v)) {
+                list1 = addToList(list1, list1Prev, v);
+                list1Prev = v;
+            } else if (isList2 == null || isList2.apply(v)) {
+                list2 = addToList(list2, list2Prev, v);
+                list2Prev = v;
+            }
+        }
+
+        if (list1Prev != null) {
+            list1Prev.next = Interval.EndMarker;
+        }
+        if (list2Prev != null) {
+            list2Prev.next = Interval.EndMarker;
+        }
+
+        assert list1Prev == null || list1Prev.next == Interval.EndMarker : "linear list ends not with sentinel";
+        assert list2Prev == null || list2Prev.next == Interval.EndMarker : "linear list ends not with sentinel";
+
+        return new Interval.Pair(list1, list2);
+    }
+
+    void sortIntervalsBeforeAllocation() {
+        int sortedLen = 0;
+        for (Interval interval : intervals) {
+            if (interval != null) {
+                sortedLen++;
+            }
+        }
+
+        Interval[] sortedList = new Interval[sortedLen];
+        int sortedIdx = 0;
+        int sortedFromMax = -1;
+
+        // special sorting algorithm: the original interval-list is almost sorted,
+        // only some intervals are swapped. So this is much faster than a complete QuickSort
+        for (Interval interval : intervals) {
+            if (interval != null) {
+                int from = interval.from();
+
+                if (sortedFromMax <= from) {
+                    sortedList[sortedIdx++] = interval;
+                    sortedFromMax = interval.from();
+                } else {
+                    // the assumption that the intervals are already sorted failed,
+                    // so this interval must be sorted in manually
+                    int j;
+                    for (j = sortedIdx - 1; j >= 0 && from < sortedList[j].from(); j--) {
+                        sortedList[j + 1] = sortedList[j];
+                    }
+                    sortedList[j + 1] = interval;
+                    sortedIdx++;
+                }
+            }
+        }
+        sortedIntervals = sortedList;
+    }
+
+    void sortIntervalsAfterAllocation() {
+        if (firstDerivedIntervalIndex == -1) {
+            // no intervals have been added during allocation, so sorted list is already up to date
+            return;
+        }
+
+        Interval[] oldList = sortedIntervals;
+        Interval[] newList = Arrays.copyOfRange(intervals, firstDerivedIntervalIndex, intervalsSize);
+        int oldLen = oldList.length;
+        int newLen = newList.length;
+
+        // conventional sort-algorithm for new intervals
+        Arrays.sort(newList, INTERVAL_COMPARATOR);
+
+        // merge old and new list (both already sorted) into one combined list
+        Interval[] combinedList = new Interval[oldLen + newLen];
+        int oldIdx = 0;
+        int newIdx = 0;
+
+        while (oldIdx + newIdx < combinedList.length) {
+            if (newIdx >= newLen || (oldIdx < oldLen && oldList[oldIdx].from() <= newList[newIdx].from())) {
+                combinedList[oldIdx + newIdx] = oldList[oldIdx];
+                oldIdx++;
+            } else {
+                combinedList[oldIdx + newIdx] = newList[newIdx];
+                newIdx++;
+            }
+        }
+
+        sortedIntervals = combinedList;
+    }
+
+    private static final Comparator<Interval> INTERVAL_COMPARATOR = new Comparator<Interval>() {
+
+        public int compare(Interval a, Interval b) {
+            if (a != null) {
+                if (b != null) {
+                    return a.from() - b.from();
+                } else {
+                    return -1;
+                }
+            } else {
+                if (b != null) {
+                    return 1;
+                } else {
+                    return 0;
+                }
+            }
+        }
+    };
+
+    public void allocateRegisters() {
+        Interval precoloredIntervals;
+        Interval notPrecoloredIntervals;
+
+        Interval.Pair result = createUnhandledLists(IS_PRECOLORED_INTERVAL, IS_VARIABLE_INTERVAL);
+        precoloredIntervals = result.first;
+        notPrecoloredIntervals = result.second;
+
+        // allocate cpu registers
+        LinearScanWalker lsw = new LinearScanWalker(this, precoloredIntervals, notPrecoloredIntervals);
+        lsw.walk();
+        lsw.finishAllocation();
+    }
+
+    // * Phase 6: resolve data flow
+    // (insert moves at edges between blocks if intervals have been split)
+
+    // wrapper for Interval.splitChildAtOpId that performs a bailout in product mode
+    // instead of returning null
+    Interval splitChildAtOpId(Interval interval, int opId, LIRInstruction.OperandMode mode) {
+        Interval result = interval.getSplitChildAtOpId(opId, mode, this);
+
+        if (result != null) {
+            if (GraalOptions.TraceLinearScanLevel >= 4) {
+                TTY.println("Split child at pos " + opId + " of interval " + interval.toString() + " is " + result.toString());
+            }
+            return result;
+        }
+
+        throw new CiBailout("LinearScan: interval is null");
+    }
+
+    Interval intervalAtBlockBegin(LIRBlock block, CiValue operand) {
+        assert operand.isVariable() : "register number out of bounds";
+        assert intervalFor(operand) != null : "no interval found";
+
+        return splitChildAtOpId(intervalFor(operand), block.firstLirInstructionId(), LIRInstruction.OperandMode.Output);
+    }
+
+    Interval intervalAtBlockEnd(LIRBlock block, CiValue operand) {
+        assert operand.isVariable() : "register number out of bounds";
+        assert intervalFor(operand) != null : "no interval found";
+
+        return splitChildAtOpId(intervalFor(operand), block.lastLirInstructionId() + 1, LIRInstruction.OperandMode.Output);
+    }
+
+    Interval intervalAtOpId(CiValue operand, int opId) {
+        assert operand.isVariable() : "register number out of bounds";
+        assert intervalFor(operand) != null : "no interval found";
+
+        return splitChildAtOpId(intervalFor(operand), opId, LIRInstruction.OperandMode.Input);
+    }
+
+    void resolveCollectMappings(LIRBlock fromBlock, LIRBlock toBlock, MoveResolver moveResolver) {
+        assert moveResolver.checkEmpty();
+
+        int numOperands = operands.size();
+        BitMap liveAtEdge = toBlock.liveIn;
+
+        // visit all variables for which the liveAtEdge bit is set
+        for (int operandNum = liveAtEdge.nextSetBit(0); operandNum >= 0; operandNum = liveAtEdge.nextSetBit(operandNum + 1)) {
+            assert operandNum < numOperands : "live information set for not exisiting interval";
+            assert fromBlock.liveOut.get(operandNum) && toBlock.liveIn.get(operandNum) : "interval not live at this edge";
+
+            CiValue liveOperand = operands.operandFor(operandNum);
+            Interval fromInterval = intervalAtBlockEnd(fromBlock, liveOperand);
+            Interval toInterval = intervalAtBlockBegin(toBlock, liveOperand);
+
+            if (fromInterval != toInterval && (fromInterval.location() != toInterval.location())) {
+                // need to insert move instruction
+                moveResolver.addMapping(fromInterval, toInterval);
+            }
+        }
+    }
+
+    void resolveFindInsertPos(LIRBlock fromBlock, LIRBlock toBlock, MoveResolver moveResolver) {
+        if (fromBlock.numberOfSux() <= 1) {
+            if (GraalOptions.TraceLinearScanLevel >= 4) {
+                TTY.println("inserting moves at end of fromBlock B%d", fromBlock.blockID());
+            }
+
+            List<LIRInstruction> instructions = fromBlock.lir().instructionsList();
+            LIRInstruction instr = instructions.get(instructions.size() - 1);
+            if (instr instanceof LIRBranch) {
+                LIRBranch branch = (LIRBranch) instr;
+                // insert moves before branch
+                assert branch.cond() == Condition.TRUE : "block does not end with an unconditional jump";
+                moveResolver.setInsertPosition(fromBlock.lir(), instructions.size() - 2);
+            } else {
+                moveResolver.setInsertPosition(fromBlock.lir(), instructions.size() - 1);
+            }
+
+        } else {
+            if (GraalOptions.TraceLinearScanLevel >= 4) {
+                TTY.println("inserting moves at beginning of toBlock B%d", toBlock.blockID());
+            }
+
+            if (GraalOptions.DetailedAsserts) {
+                assert fromBlock.lir().instructionsList().get(0) instanceof LIRLabel : "block does not start with a label";
+
+                // because the number of predecessor edges matches the number of
+                // successor edges, blocks which are reached by switch statements
+                // may have be more than one predecessor but it will be guaranteed
+                // that all predecessors will be the same.
+                for (int i = 0; i < toBlock.numberOfPreds(); i++) {
+                    assert fromBlock == toBlock.predAt(i) : "all critical edges must be broken";
+                }
+            }
+
+            moveResolver.setInsertPosition(toBlock.lir(), 0);
+        }
+    }
+
+    /**
+     * Inserts necessary moves (spilling or reloading) at edges between blocks for intervals that
+     * have been split.
+     */
+    void resolveDataFlow() {
+        int numBlocks = blockCount();
+        MoveResolver moveResolver = new MoveResolver(this);
+        BitMap blockCompleted = new BitMap(numBlocks);
+        BitMap alreadyResolved = new BitMap(numBlocks);
+
+        int i;
+        for (i = 0; i < numBlocks; i++) {
+            LIRBlock block = blockAt(i);
+
+            // check if block has only one predecessor and only one successor
+            if (block.numberOfPreds() == 1 && block.numberOfSux() == 1) {
+                List<LIRInstruction> instructions = block.lir().instructionsList();
+                assert instructions.get(0).code == LIROpcode.Label : "block must start with label";
+                assert instructions.get(instructions.size() - 1).code == LIROpcode.Branch : "block with successors must end with branch (" + block + "), " + instructions.get(instructions.size() - 1);
+                assert ((LIRBranch) instructions.get(instructions.size() - 1)).cond() == Condition.TRUE : "block with successor must end with unconditional branch";
+
+                // check if block is empty (only label and branch)
+                if (instructions.size() == 2) {
+                    LIRBlock pred = block.predAt(0);
+                    LIRBlock sux = block.suxAt(0);
+
+                    // prevent optimization of two consecutive blocks
+                    if (!blockCompleted.get(pred.linearScanNumber()) && !blockCompleted.get(sux.linearScanNumber())) {
+                        if (GraalOptions.TraceLinearScanLevel >= 3) {
+                            TTY.println(" optimizing empty block B%d (pred: B%d, sux: B%d)", block.blockID(), pred.blockID(), sux.blockID());
+                        }
+                        blockCompleted.set(block.linearScanNumber());
+
+                        // directly resolve between pred and sux (without looking at the empty block between)
+                        resolveCollectMappings(pred, sux, moveResolver);
+                        if (moveResolver.hasMappings()) {
+                            moveResolver.setInsertPosition(block.lir(), 0);
+                            moveResolver.resolveAndAppendMoves();
+                        }
+                    }
+                }
+            }
+        }
+
+        for (i = 0; i < numBlocks; i++) {
+            if (!blockCompleted.get(i)) {
+                LIRBlock fromBlock = blockAt(i);
+                alreadyResolved.setFrom(blockCompleted);
+
+                int numSux = fromBlock.numberOfSux();
+                for (int s = 0; s < numSux; s++) {
+                    LIRBlock toBlock = fromBlock.suxAt(s);
+
+                    // check for duplicate edges between the same blocks (can happen with switch blocks)
+                    if (!alreadyResolved.get(toBlock.linearScanNumber())) {
+                        if (GraalOptions.TraceLinearScanLevel >= 3) {
+                            TTY.println(" processing edge between B%d and B%d", fromBlock.blockID(), toBlock.blockID());
+                        }
+                        alreadyResolved.set(toBlock.linearScanNumber());
+
+                        // collect all intervals that have been split between fromBlock and toBlock
+                        resolveCollectMappings(fromBlock, toBlock, moveResolver);
+                        if (moveResolver.hasMappings()) {
+                            resolveFindInsertPos(fromBlock, toBlock, moveResolver);
+                            moveResolver.resolveAndAppendMoves();
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    // * Phase 7: assign register numbers back to LIR
+    // (includes computation of debug information and oop maps)
+
+    boolean verifyAssignedLocation(Interval interval, CiValue location) {
+        CiKind kind = interval.kind();
+
+        assert location.isRegister() || location.isStackSlot();
+
+        if (location.isRegister()) {
+            CiRegister reg = location.asRegister();
+
+            // register
+            switch (kind) {
+                case Byte:
+                case Char:
+                case Short:
+                case Jsr:
+                case Word:
+                case Object:
+                case Int: {
+                    assert reg.isCpu() : "not cpu register";
+                    break;
+                }
+
+                case Long: {
+                    assert reg.isCpu() : "not cpu register";
+                    break;
+                }
+
+                case Float: {
+                    assert !compilation.target.arch.isX86() || reg.isFpu() : "not xmm register: " + reg;
+                    break;
+                }
+
+                case Double: {
+                    assert !compilation.target.arch.isX86() || reg.isFpu() : "not xmm register: " + reg;
+                    break;
+                }
+
+                default: {
+                    throw Util.shouldNotReachHere();
+                }
+            }
+        }
+        return true;
+    }
+
+    CiStackSlot canonicalSpillOpr(Interval interval) {
+        assert interval.spillSlot() != null : "canonical spill slot not set";
+        return interval.spillSlot();
+    }
+
+    /**
+     * Assigns the allocated location for an LIR instruction operand back into the instruction.
+     *
+     * @param operand an LIR instruction operand
+     * @param opId the id of the LIR instruction using {@code operand}
+     * @param mode the usage mode for {@code operand} by the instruction
+     * @return the location assigned for the operand
+     */
+    private CiValue colorLirOperand(CiVariable operand, int opId, OperandMode mode) {
+        Interval interval = intervalFor(operand);
+        assert interval != null : "interval must exist";
+
+        if (opId != -1) {
+            if (GraalOptions.DetailedAsserts) {
+                LIRBlock block = blockForId(opId);
+                if (block.numberOfSux() <= 1 && opId == block.lastLirInstructionId()) {
+                    // check if spill moves could have been appended at the end of this block, but
+                    // before the branch instruction. So the split child information for this branch would
+                    // be incorrect.
+                    LIRInstruction instr = block.lir().instructionsList().get(block.lir().instructionsList().size() - 1);
+                    if (instr instanceof LIRBranch) {
+                        LIRBranch branch = (LIRBranch) instr;
+                        if (block.liveOut.get(operandNumber(operand))) {
+                            assert branch.cond() == Condition.TRUE : "block does not end with an unconditional jump";
+                            throw new CiBailout("can't get split child for the last branch of a block because the information would be incorrect (moves are inserted before the branch in resolveDataFlow)");
+                        }
+                    }
+                }
+            }
+
+            // operands are not changed when an interval is split during allocation,
+            // so search the right interval here
+            interval = splitChildAtOpId(interval, opId, mode);
+        }
+
+        return interval.location();
+    }
+
+    IntervalWalker initComputeOopMaps() {
+        // setup lists of potential oops for walking
+        Interval oopIntervals;
+        Interval nonOopIntervals;
+
+        oopIntervals = createUnhandledLists(IS_OOP_INTERVAL, null).first;
+
+        // intervals that have no oops inside need not to be processed.
+        // to ensure a walking until the last instruction id, add a dummy interval
+        // with a high operation id
+        nonOopIntervals = new Interval(CiValue.IllegalValue, -1);
+        nonOopIntervals.addRange(Integer.MAX_VALUE - 2, Integer.MAX_VALUE - 1);
+
+        return new IntervalWalker(this, oopIntervals, nonOopIntervals);
+    }
+
+    void computeOopMap(IntervalWalker iw, LIRInstruction op, LIRDebugInfo info, boolean isCallSite, BitMap frameRefMap, BitMap regRefMap) {
+        if (GraalOptions.TraceLinearScanLevel >= 3) {
+            TTY.println("creating oop map at opId %d", op.id());
+        }
+
+        // walk before the current operation . intervals that start at
+        // the operation (i.e. output operands of the operation) are not
+        // included in the oop map
+        iw.walkBefore(op.id());
+
+        // Iterate through active intervals
+        for (Interval interval = iw.activeLists.get(RegisterBinding.Fixed); interval != Interval.EndMarker; interval = interval.next) {
+            CiValue operand = interval.operand;
+
+            assert interval.currentFrom() <= op.id() && op.id() <= interval.currentTo() : "interval should not be active otherwise";
+            assert interval.operand.isVariable() : "fixed interval found";
+
+            // Check if this range covers the instruction. Intervals that
+            // start or end at the current operation are not included in the
+            // oop map, except in the case of patching moves. For patching
+            // moves, any intervals which end at this instruction are included
+            // in the oop map since we may safepoint while doing the patch
+            // before we've consumed the inputs.
+            if (op.id() < interval.currentTo()) {
+                // caller-save registers must not be included into oop-maps at calls
+                assert !isCallSite || !operand.isRegister() || !isCallerSave(operand) : "interval is in a caller-save register at a call . register will be overwritten";
+
+                CiValue location = interval.location();
+                if (location.isStackSlot()) {
+                    location = frameMap.toStackAddress((CiStackSlot) location);
+                }
+                info.setOop(location, compilation, frameRefMap, regRefMap);
+
+                // Spill optimization: when the stack value is guaranteed to be always correct,
+                // then it must be added to the oop map even if the interval is currently in a register
+                if (interval.alwaysInMemory() && op.id() > interval.spillDefinitionPos() && !interval.location().equals(interval.spillSlot())) {
+                    assert interval.spillDefinitionPos() > 0 : "position not set correctly";
+                    assert interval.spillSlot() != null : "no spill slot assigned";
+                    assert !interval.operand.isRegister() : "interval is on stack :  so stack slot is registered twice";
+                    info.setOop(frameMap.toStackAddress(interval.spillSlot()), compilation, frameRefMap, regRefMap);
+                }
+            }
+        }
+    }
+
+    private boolean isCallerSave(CiValue operand) {
+        return attributes(operand.asRegister()).isCallerSave;
+    }
+
+    void computeOopMap(IntervalWalker iw, LIRInstruction op, LIRDebugInfo info, BitMap frameRefMap, BitMap regRefMap) {
+        computeOopMap(iw, op, info, op.hasCall, frameRefMap, regRefMap);
+        if (op instanceof LIRCall) {
+            List<CiValue> pointerSlots = ((LIRCall) op).pointerSlots;
+            if (pointerSlots != null) {
+                for (CiValue v : pointerSlots) {
+                    info.setOop(v, compilation, frameRefMap, regRefMap);
+                }
+            }
+        } else if (op instanceof LIRXirInstruction) {
+            List<CiValue> pointerSlots = ((LIRXirInstruction) op).pointerSlots;
+            if (pointerSlots != null) {
+                for (CiValue v : pointerSlots) {
+                    info.setOop(v, compilation, frameRefMap, regRefMap);
+                }
+            }
+        }
+    }
+
+    public static ThreadLocal<ServiceLoader<FrameModifier>> frameModifierLoader = new ThreadLocal<ServiceLoader<FrameModifier>>();
+
+    private CiFrame overrideFrame(CiFrame frame) {
+        ServiceLoader<FrameModifier> serviceLoader = frameModifierLoader.get();
+        if (serviceLoader == null) {
+            serviceLoader = ServiceLoader.load(FrameModifier.class);
+            frameModifierLoader.set(serviceLoader);
+        }
+
+        CiFrame result = frame;
+        for (FrameModifier modifier : serviceLoader) {
+            result = modifier.getFrame(compilation.runtime, result);
+        }
+        return result;
+    }
+
+
+    private class DebugFrameBuilder {
+
+        private final FrameState topState;
+        private final int opId;
+        private final BitMap frameRefMap;
+
+        private HashMap<VirtualObject, CiVirtualObject> virtualObjects;
+
+        public DebugFrameBuilder(FrameState topState, int opId, BitMap frameRefMap) {
+            this.topState = topState;
+            this.opId = opId;
+            this.frameRefMap = frameRefMap;
+        }
+
+        private CiValue toCiValue(Value value) {
+            if (value instanceof VirtualObject) {
+                if (virtualObjects == null) {
+                    virtualObjects = new HashMap<VirtualObject, CiVirtualObject>();
+                }
+                VirtualObject obj = (VirtualObject) value;
+                CiVirtualObject ciObj = virtualObjects.get(value);
+                if (ciObj == null) {
+                    ciObj = CiVirtualObject.get(obj.type(), null, value.id());
+                    virtualObjects.put(obj, ciObj);
+                }
+                return ciObj;
+            } else if (value != null && value.operand() != CiValue.IllegalValue) {
+                CiValue operand = value.operand();
+                Constant con = null;
+                if (value instanceof Constant) {
+                    con = (Constant) value;
+                }
+
+                assert con == null || operand.isVariable() || operand.isConstant() || operand.isIllegal() : "Constant instructions have only constant operands (or illegal if constant is optimized away)";
+
+                int tempOpId = this.opId;
+                if (operand.isVariable()) {
+                    OperandMode mode = OperandMode.Input;
+                    LIRBlock block = blockForId(tempOpId);
+                    if (block.numberOfSux() == 1 && tempOpId == block.lastLirInstructionId()) {
+                        // generating debug information for the last instruction of a block.
+                        // if this instruction is a branch, spill moves are inserted before this branch
+                        // and so the wrong operand would be returned (spill moves at block boundaries are not
+                        // considered in the live ranges of intervals)
+                        // Solution: use the first opId of the branch target block instead.
+                        final LIRInstruction instr = block.lir().instructionsList().get(block.lir().instructionsList().size() - 1);
+                        if (instr instanceof LIRBranch) {
+                            if (block.liveOut.get(operandNumber(operand))) {
+                                tempOpId = block.suxAt(0).firstLirInstructionId();
+                                mode = OperandMode.Output;
+                            }
+                        }
+                    }
+
+                    // Get current location of operand
+                    // The operand must be live because debug information is considered when building the intervals
+                    // if the interval is not live, colorLirOperand will cause an assert on failure
+                    operand = colorLirOperand((CiVariable) operand, tempOpId, mode);
+                    assert !hasCall(tempOpId) || operand.isStackSlot() || !isCallerSave(operand) : "cannot have caller-save register operands at calls";
+                    return operand;
+                } else if (operand.isRegister()) {
+                    assert false : "must not reach here";
+                    return operand;
+                } else {
+                    assert value instanceof Constant;
+                    assert operand.isConstant() : "operand must be constant";
+                    return operand;
+                }
+            } else {
+                // return a dummy value because real value not needed
+                return CiValue.IllegalValue;
+            }
+        }
+
+        private CiFrame computeFrameForState(FrameState state) {
+            CiValue[] values = new CiValue[state.valuesSize() + state.locksSize()];
+            int valueIndex = 0;
+
+            for (int i = 0; i < state.valuesSize(); i++) {
+                values[valueIndex++] = toCiValue(state.valueAt(i));
+            }
+
+            for (int i = 0; i < state.locksSize(); i++) {
+                if (compilation.runtime.sizeOfBasicObjectLock() != 0) {
+                    CiStackSlot monitorAddress = frameMap.toMonitorBaseStackAddress(i);
+                    values[valueIndex++] = monitorAddress;
+                    CiStackSlot objectAddress = frameMap.toMonitorObjectStackAddress(i);
+                    frameRefMap.set(objectAddress.index());
+                } else {
+                    Value lock = state.lockAt(i);
+                    if (lock.isConstant() && compilation.runtime.asJavaClass(lock.asConstant()) != null) {
+                        // lock on class for synchronized static method
+                        values[valueIndex++] = lock.asConstant();
+                    } else {
+                        values[valueIndex++] = toCiValue(lock);
+                    }
+                }
+            }
+            CiFrame caller = null;
+            if (state.outerFrameState() != null) {
+                caller = computeFrameForState(state.outerFrameState());
+            }
+            CiFrame frame = new CiFrame(caller, state.method, state.bci, state.rethrowException(), values, state.localsSize(), state.stackSize(), state.locksSize());
+            if (GraalOptions.Extend) {
+                frame = overrideFrame(frame);
+            }
+            return frame;
+        }
+
+        public CiFrame build() {
+            CiFrame frame = computeFrameForState(topState);
+
+            if (virtualObjects != null) {
+                // collect all VirtualObjectField instances:
+                HashMap<VirtualObject, VirtualObjectField> objectStates = new HashMap<VirtualObject, VirtualObjectField>();
+                FrameState current = topState;
+                do {
+                    for (Node n : current.virtualObjectMappings()) {
+                        VirtualObjectField field = (VirtualObjectField) n;
+                        // null states occur for objects with 0 fields
+                        if (field != null && !objectStates.containsKey(field.object())) {
+                            objectStates.put(field.object(), field);
+                        }
+                    }
+                    current = current.outerFrameState();
+                } while (current != null);
+                // fill in the CiVirtualObject values:
+                // during this process new CiVirtualObjects might be discovered, so repeat until no more changes occur.
+                boolean changed;
+                do {
+                    changed = false;
+                    HashMap<VirtualObject, CiVirtualObject> virtualObjectsCopy = new HashMap<VirtualObject, CiVirtualObject>(virtualObjects);
+                    for (Entry<VirtualObject, CiVirtualObject> entry : virtualObjectsCopy.entrySet()) {
+                        if (entry.getValue().values() == null) {
+                            VirtualObject vobj = entry.getKey();
+                            CiValue[] values = new CiValue[vobj.fields().length];
+                            entry.getValue().setValues(values);
+                            if (vobj.fields().length > 0) {
+                                changed = true;
+                                FloatingNode currentField = objectStates.get(vobj);
+                                assert currentField != null;
+                                do {
+                                    if (currentField instanceof VirtualObjectField) {
+                                        int index = ((VirtualObjectField) currentField).index();
+                                        if (values[index] == null) {
+                                            values[index] = toCiValue(((VirtualObjectField) currentField).input());
+                                        }
+                                        currentField = ((VirtualObjectField) currentField).lastState();
+                                    } else {
+                                        assert currentField instanceof Phi : currentField;
+                                        currentField = (FloatingNode) ((Phi) currentField).valueAt(0);
+                                    }
+                                } while (currentField != null);
+                            }
+                        }
+                    }
+                } while (changed);
+            }
+            return frame;
+        }
+    }
+
+    private void computeDebugInfo(IntervalWalker iw, LIRInstruction op) {
+        assert iw != null : "interval walker needed for debug information";
+        computeDebugInfo(iw, op, op.info);
+
+        if (op instanceof LIRXirInstruction) {
+            LIRXirInstruction xir = (LIRXirInstruction) op;
+            if (xir.infoAfter != null) {
+                computeDebugInfo(iw, op, xir.infoAfter);
+            }
+        }
+    }
+
+
+    private void computeDebugInfo(IntervalWalker iw, LIRInstruction op, LIRDebugInfo info) {
+        if (info != null) {
+            if (info.debugInfo == null) {
+                int frameSize = compilation.frameMap().frameSize();
+                int frameWords = frameSize / compilation.target.spillSlotSize;
+                BitMap frameRefMap = new BitMap(frameWords);
+                BitMap regRefMap = !op.hasCall ? new BitMap(compilation.target.arch.registerReferenceMapBitCount) : null;
+                CiFrame frame = compilation.placeholderState != null ? null : computeFrame(info.state, op.id(), frameRefMap);
+                computeOopMap(iw, op, info, frameRefMap, regRefMap);
+                info.debugInfo = new CiDebugInfo(frame, regRefMap, frameRefMap);
+            } else if (GraalOptions.DetailedAsserts) {
+                assert info.debugInfo.frame().equals(computeFrame(info.state, op.id(), new BitMap(info.debugInfo.frameRefMap.size())));
+            }
+        }
+    }
+
+    CiFrame computeFrame(FrameState state, int opId, BitMap frameRefMap) {
+        if (GraalOptions.TraceLinearScanLevel >= 3) {
+            TTY.println("creating debug information at opId %d", opId);
+        }
+        return new DebugFrameBuilder(state, opId, frameRefMap).build();
+    }
+
+    private void assignLocations(List<LIRInstruction> instructions, IntervalWalker iw) {
+        int numInst = instructions.size();
+        boolean hasDead = false;
+
+        for (int j = 0; j < numInst; j++) {
+            LIRInstruction op = instructions.get(j);
+            if (op == null) { // this can happen when spill-moves are removed in eliminateSpillMoves
+                hasDead = true;
+                continue;
+            }
+
+            // iterate all modes of the visitor and process all virtual operands
+            for (LIRInstruction.OperandMode mode : LIRInstruction.OPERAND_MODES) {
+                int n = op.operandCount(mode);
+                for (int k = 0; k < n; k++) {
+                    CiValue operand = op.operandAt(mode, k);
+                    if (operand.isVariable()) {
+                        op.setOperandAt(mode, k, colorLirOperand((CiVariable) operand, op.id(), mode));
+                    }
+                }
+            }
+
+            if (op.info != null) {
+                // compute reference map and debug information
+                computeDebugInfo(iw, op);
+            }
+
+            // make sure we haven't made the op invalid.
+            assert op.verify();
+
+            // remove useless moves
+            if (op.code == LIROpcode.Move) {
+                CiValue src = op.operand(0);
+                CiValue dst = op.result();
+                if (dst == src || src.equals(dst)) {
+                    // TODO: what about o.f = o.f and exceptions?
+                    instructions.set(j, null);
+                    hasDead = true;
+                }
+            }
+        }
+
+        if (hasDead) {
+            // iterate all instructions of the block and remove all null-values.
+            int insertPoint = 0;
+            for (int j = 0; j < numInst; j++) {
+                LIRInstruction op = instructions.get(j);
+                if (op != null) {
+                    if (insertPoint != j) {
+                        instructions.set(insertPoint, op);
+                    }
+                    insertPoint++;
+                }
+            }
+            Util.truncate(instructions, insertPoint);
+        }
+    }
+
+    private void assignLocations() {
+        IntervalWalker iw = initComputeOopMaps();
+        for (LIRBlock block : sortedBlocks) {
+            assignLocations(block.lir().instructionsList(), iw);
+        }
+    }
+
+    public void allocate() {
+        if (GraalOptions.Time) {
+            GraalTimers.LIFETIME_ANALYSIS.start();
+        }
+
+        numberInstructions();
+
+        printLir("Before register allocation", true);
+
+        computeLocalLiveSets();
+        computeGlobalLiveSets();
+
+        buildIntervals();
+        sortIntervalsBeforeAllocation();
+
+        if (GraalOptions.Time) {
+            GraalTimers.LIFETIME_ANALYSIS.stop();
+            GraalTimers.LINEAR_SCAN.start();
+        }
+
+        printIntervals("Before register allocation");
+
+        allocateRegisters();
+
+        if (GraalOptions.Time) {
+            GraalTimers.LINEAR_SCAN.stop();
+            GraalTimers.RESOLUTION.start();
+        }
+
+        resolveDataFlow();
+
+        if (GraalOptions.Time) {
+            GraalTimers.RESOLUTION.stop();
+            GraalTimers.DEBUG_INFO.start();
+        }
+
+        GraalMetrics.LSRASpills += (maxSpills - frameMap.initialSpillSlot());
+
+        // fill in number of spill slots into frameMap
+        frameMap.finalizeFrame(maxSpills);
+
+        printIntervals("After register allocation");
+        printLir("After register allocation", true);
+
+        sortIntervalsAfterAllocation();
+
+        if (GraalOptions.DetailedAsserts) {
+            verify();
+        }
+
+        eliminateSpillMoves();
+        assignLocations();
+
+        if (GraalOptions.DetailedAsserts) {
+            verifyIntervals();
+        }
+
+        if (GraalOptions.Time) {
+            GraalTimers.DEBUG_INFO.stop();
+            GraalTimers.CODE_CREATE.start();
+        }
+
+        printLir("After register number assignment", true);
+        EdgeMoveOptimizer.optimize(ir.linearScanOrder());
+        ControlFlowOptimizer.optimize(ir);
+        printLir("After control flow optimization", false);
+    }
+
+    void printIntervals(String label) {
+        if (GraalOptions.TraceLinearScanLevel >= 1) {
+            int i;
+            TTY.println();
+            TTY.println(label);
+
+            for (Interval interval : intervals) {
+                if (interval != null) {
+                    TTY.out().println(interval.logString(this));
+                }
+            }
+
+            TTY.println();
+            TTY.println("--- Basic Blocks ---");
+            for (i = 0; i < blockCount(); i++) {
+                LIRBlock block = blockAt(i);
+                TTY.print("B%d [%d, %d, %d, %d] ", block.blockID(), block.firstLirInstructionId(), block.lastLirInstructionId(), block.loopIndex(), block.loopDepth());
+            }
+            TTY.println();
+            TTY.println();
+        }
+
+        if (compilation.compiler.isObserved()) {
+            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, label, this, intervals, intervalsSize));
+        }
+    }
+
+    void printLir(String label, boolean hirValid) {
+        if (GraalOptions.TraceLinearScanLevel >= 1 && !TTY.isSuppressed()) {
+            TTY.println();
+            TTY.println(label);
+            LIRList.printLIR(ir.linearScanOrder());
+            TTY.println();
+        }
+
+        if (compilation.compiler.isObserved()) {
+            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, label, /*compilation.graph*/ null, hirValid, true));
+        }
+    }
+
+    boolean verify() {
+        // (check that all intervals have a correct register and that no registers are overwritten)
+        if (GraalOptions.TraceLinearScanLevel >= 2) {
+            TTY.println(" verifying intervals *");
+        }
+        verifyIntervals();
+
+        if (GraalOptions.TraceLinearScanLevel >= 2) {
+            TTY.println(" verifying that no oops are in fixed intervals *");
+        }
+        //verifyNoOopsInFixedIntervals();
+
+        if (GraalOptions.TraceLinearScanLevel >= 2) {
+            TTY.println(" verifying that unpinned constants are not alive across block boundaries");
+        }
+        verifyConstants();
+
+        if (GraalOptions.TraceLinearScanLevel >= 2) {
+            TTY.println(" verifying register allocation *");
+        }
+        verifyRegisters();
+
+        if (GraalOptions.TraceLinearScanLevel >= 2) {
+            TTY.println(" no errors found *");
+        }
+
+        return true;
+    }
+
+    private void verifyRegisters() {
+        RegisterVerifier verifier = new RegisterVerifier(this);
+        verifier.verify(blockAt(0));
+    }
+
+    void verifyIntervals() {
+        int len = intervalsSize;
+
+        for (int i = 0; i < len; i++) {
+            Interval i1 = intervals[i];
+            if (i1 == null) {
+                continue;
+            }
+
+            i1.checkSplitChildren();
+
+            if (i1.operandNumber != i) {
+                TTY.println("Interval %d is on position %d in list", i1.operandNumber, i);
+                TTY.println(i1.logString(this));
+                throw new CiBailout("");
+            }
+
+            if (i1.operand.isVariable() && i1.kind() == CiKind.Illegal) {
+                TTY.println("Interval %d has no type assigned", i1.operandNumber);
+                TTY.println(i1.logString(this));
+                throw new CiBailout("");
+            }
+
+            if (i1.location() == null) {
+                TTY.println("Interval %d has no register assigned", i1.operandNumber);
+                TTY.println(i1.logString(this));
+                throw new CiBailout("");
+            }
+
+            if (!isProcessed(i1.location())) {
+                TTY.println("Can not have an Interval for an ignored register " + i1.location());
+                TTY.println(i1.logString(this));
+                throw new CiBailout("");
+            }
+
+            if (i1.first() == Range.EndMarker) {
+                TTY.println("Interval %d has no Range", i1.operandNumber);
+                TTY.println(i1.logString(this));
+                throw new CiBailout("");
+            }
+
+            for (Range r = i1.first(); r != Range.EndMarker; r = r.next) {
+                if (r.from >= r.to) {
+                    TTY.println("Interval %d has zero length range", i1.operandNumber);
+                    TTY.println(i1.logString(this));
+                    throw new CiBailout("");
+                }
+            }
+
+            for (int j = i + 1; j < len; j++) {
+                Interval i2 = intervals[j];
+                if (i2 == null) {
+                    continue;
+                }
+
+                // special intervals that are created in MoveResolver
+                // . ignore them because the range information has no meaning there
+                if (i1.from() == 1 && i1.to() == 2) {
+                    continue;
+                }
+                if (i2.from() == 1 && i2.to() == 2) {
+                    continue;
+                }
+                CiValue l1 = i1.location();
+                CiValue l2 = i2.location();
+                if (i1.intersects(i2) && (l1.equals(l2))) {
+                    if (GraalOptions.DetailedAsserts) {
+                        TTY.println("Intervals %d and %d overlap and have the same register assigned", i1.operandNumber, i2.operandNumber);
+                        TTY.println(i1.logString(this));
+                        TTY.println(i2.logString(this));
+                    }
+                    throw new CiBailout("");
+                }
+            }
+        }
+    }
+
+    void verifyNoOopsInFixedIntervals() {
+        Interval fixedIntervals;
+        Interval otherIntervals;
+        fixedIntervals = createUnhandledLists(IS_PRECOLORED_INTERVAL, null).first;
+        // to ensure a walking until the last instruction id, add a dummy interval
+        // with a high operation id
+        otherIntervals = new Interval(CiValue.IllegalValue, -1);
+        otherIntervals.addRange(Integer.MAX_VALUE - 2, Integer.MAX_VALUE - 1);
+        IntervalWalker iw = new IntervalWalker(this, fixedIntervals, otherIntervals);
+
+        for (int i = 0; i < blockCount(); i++) {
+            LIRBlock block = blockAt(i);
+
+            List<LIRInstruction> instructions = block.lir().instructionsList();
+
+            for (int j = 0; j < instructions.size(); j++) {
+                LIRInstruction op = instructions.get(j);
+
+                if (op.info != null) {
+                    iw.walkBefore(op.id());
+                    boolean checkLive = true;
+
+                    // Make sure none of the fixed registers is live across an
+                    // oopmap since we can't handle that correctly.
+                    if (checkLive) {
+                        for (Interval interval = iw.activeLists.get(RegisterBinding.Fixed); interval != Interval.EndMarker; interval = interval.next) {
+                            if (interval.currentTo() > op.id() + 1) {
+                                // This interval is live out of this op so make sure
+                                // that this interval represents some value that's
+                                // referenced by this op either as an input or output.
+                                boolean ok = false;
+                                for (LIRInstruction.OperandMode mode : LIRInstruction.OPERAND_MODES) {
+                                    int n = op.operandCount(mode);
+                                    for (int k = 0; k < n; k++) {
+                                        CiValue operand = op.operandAt(mode, k);
+                                        if (operand.isRegister()) {
+                                            if (intervalFor(operand) == interval) {
+                                                ok = true;
+                                                break;
+                                            }
+                                        }
+                                    }
+                                }
+                                assert ok : "fixed intervals should never be live across an oopmap point";
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    void verifyConstants() {
+        int numBlocks = blockCount();
+
+        for (int i = 0; i < numBlocks; i++) {
+            LIRBlock block = blockAt(i);
+            BitMap liveAtEdge = block.liveIn;
+
+            // visit all operands where the liveAtEdge bit is set
+            for (int operandNum = liveAtEdge.nextSetBit(0); operandNum >= 0; operandNum = liveAtEdge.nextSetBit(operandNum + 1)) {
+                if (GraalOptions.TraceLinearScanLevel >= 4) {
+                    TTY.println("checking interval %d of block B%d", operandNum, block.blockID());
+                }
+                CiValue operand = operands.operandFor(operandNum);
+                assert operand.isVariable() : "value must have variable operand";
+                Value value = gen.operands.instructionForResult(((CiVariable) operand));
+                assert value != null : "all intervals live across block boundaries must have Value";
+                // TKR assert value.asConstant() == null || value.isPinned() :
+                // "only pinned constants can be alive accross block boundaries";
+            }
+        }
+    }
+
+    public int numberOfSpillSlots(CiKind kind) {
+        return compilation.target.spillSlots(kind);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScanWalker.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,980 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.alloc;
+
+import static com.sun.cri.ci.CiUtil.*;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.alloc.Interval.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.lir.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ci.CiRegister.*;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+final class LinearScanWalker extends IntervalWalker {
+
+    private CiRegister[] availableRegs;
+
+    private final int[] usePos;
+    private final int[] blockPos;
+
+    private List<Interval>[] spillIntervals;
+
+    private MoveResolver moveResolver; // for ordering spill moves
+
+    // accessors mapped to same functions in class LinearScan
+    int blockCount() {
+        return allocator.blockCount();
+    }
+
+    LIRBlock blockAt(int idx) {
+        return allocator.blockAt(idx);
+    }
+
+    LIRBlock blockOfOpWithId(int opId) {
+        return allocator.blockForId(opId);
+    }
+
+    LinearScanWalker(LinearScan allocator, Interval unhandledFixedFirst, Interval unhandledAnyFirst) {
+        super(allocator, unhandledFixedFirst, unhandledAnyFirst);
+        moveResolver = new MoveResolver(allocator);
+        spillIntervals = Util.uncheckedCast(new List[allocator.registers.length]);
+        for (int i = 0; i < allocator.registers.length; i++) {
+            spillIntervals[i] = new ArrayList<Interval>(2);
+        }
+        usePos = new int[allocator.registers.length];
+        blockPos = new int[allocator.registers.length];
+    }
+
+    void initUseLists(boolean onlyProcessUsePos) {
+        for (CiRegister register : availableRegs) {
+            int i = register.number;
+            usePos[i] = Integer.MAX_VALUE;
+
+            if (!onlyProcessUsePos) {
+                blockPos[i] = Integer.MAX_VALUE;
+                spillIntervals[i].clear();
+            }
+        }
+    }
+
+    void excludeFromUse(Interval i) {
+        CiValue location = i.location();
+        int i1 = location.asRegister().number;
+        if (i1 >= availableRegs[0].number && i1 <= availableRegs[availableRegs.length - 1].number) {
+            usePos[i1] = 0;
+        }
+    }
+
+    void setUsePos(Interval interval, int usePos, boolean onlyProcessUsePos) {
+        if (usePos != -1) {
+            assert usePos != 0 : "must use excludeFromUse to set usePos to 0";
+            int i = interval.location().asRegister().number;
+            if (i >= availableRegs[0].number && i <= availableRegs[availableRegs.length - 1].number) {
+                if (this.usePos[i] > usePos) {
+                    this.usePos[i] = usePos;
+                }
+                if (!onlyProcessUsePos) {
+                    spillIntervals[i].add(interval);
+                }
+            }
+        }
+    }
+
+    void setBlockPos(Interval i, int blockPos) {
+        if (blockPos != -1) {
+            int reg = i.location().asRegister().number;
+            if (reg >= availableRegs[0].number && reg <= availableRegs[availableRegs.length - 1].number) {
+                if (this.blockPos[reg] > blockPos) {
+                    this.blockPos[reg] = blockPos;
+                }
+                if (usePos[reg] > blockPos) {
+                    usePos[reg] = blockPos;
+                }
+            }
+        }
+    }
+
+    void freeExcludeActiveFixed() {
+        Interval interval = activeLists.get(RegisterBinding.Fixed);
+        while (interval != Interval.EndMarker) {
+            assert interval.location().isRegister() : "active interval must have a register assigned";
+            excludeFromUse(interval);
+            interval = interval.next;
+        }
+    }
+
+    void freeExcludeActiveAny() {
+        Interval interval = activeLists.get(RegisterBinding.Any);
+        while (interval != Interval.EndMarker) {
+            assert interval.location().isRegister() : "active interval must have a register assigned";
+            excludeFromUse(interval);
+            interval = interval.next;
+        }
+    }
+
+    void freeCollectInactiveFixed(Interval current) {
+        Interval interval = inactiveLists.get(RegisterBinding.Fixed);
+        while (interval != Interval.EndMarker) {
+            if (current.to() <= interval.currentFrom()) {
+                assert interval.currentIntersectsAt(current) == -1 : "must not intersect";
+                setUsePos(interval, interval.currentFrom(), true);
+            } else {
+                setUsePos(interval, interval.currentIntersectsAt(current), true);
+            }
+            interval = interval.next;
+        }
+    }
+
+    void freeCollectInactiveAny(Interval current) {
+        Interval interval = inactiveLists.get(RegisterBinding.Any);
+        while (interval != Interval.EndMarker) {
+            setUsePos(interval, interval.currentIntersectsAt(current), true);
+            interval = interval.next;
+        }
+    }
+
+    void freeCollectUnhandled(RegisterBinding kind, Interval current) {
+        Interval interval = unhandledLists.get(kind);
+        while (interval != Interval.EndMarker) {
+            setUsePos(interval, interval.intersectsAt(current), true);
+            if (kind == RegisterBinding.Fixed && current.to() <= interval.from()) {
+                setUsePos(interval, interval.from(), true);
+            }
+            interval = interval.next;
+        }
+    }
+
+    void spillExcludeActiveFixed() {
+        Interval interval = activeLists.get(RegisterBinding.Fixed);
+        while (interval != Interval.EndMarker) {
+            excludeFromUse(interval);
+            interval = interval.next;
+        }
+    }
+
+    void spillBlockUnhandledFixed(Interval current) {
+        Interval interval = unhandledLists.get(RegisterBinding.Fixed);
+        while (interval != Interval.EndMarker) {
+            setBlockPos(interval, interval.intersectsAt(current));
+            interval = interval.next;
+        }
+    }
+
+    void spillBlockInactiveFixed(Interval current) {
+        Interval interval = inactiveLists.get(RegisterBinding.Fixed);
+        while (interval != Interval.EndMarker) {
+            if (current.to() > interval.currentFrom()) {
+                setBlockPos(interval, interval.currentIntersectsAt(current));
+            } else {
+                assert interval.currentIntersectsAt(current) == -1 : "invalid optimization: intervals intersect";
+            }
+
+            interval = interval.next;
+        }
+    }
+
+    void spillCollectActiveAny() {
+        Interval interval = activeLists.get(RegisterBinding.Any);
+        while (interval != Interval.EndMarker) {
+            setUsePos(interval, Math.min(interval.nextUsage(RegisterPriority.LiveAtLoopEnd, currentPosition), interval.to()), false);
+            interval = interval.next;
+        }
+    }
+
+    void spillCollectInactiveAny(Interval current) {
+        Interval interval = inactiveLists.get(RegisterBinding.Any);
+        while (interval != Interval.EndMarker) {
+            if (interval.currentIntersects(current)) {
+                setUsePos(interval, Math.min(interval.nextUsage(RegisterPriority.LiveAtLoopEnd, currentPosition), interval.to()), false);
+            }
+            interval = interval.next;
+        }
+    }
+
+    void insertMove(int opId, Interval srcIt, Interval dstIt) {
+        // output all moves here. When source and target are equal, the move is
+        // optimized away later in assignRegNums
+
+        opId = (opId + 1) & ~1;
+        LIRBlock opBlock = allocator.blockForId(opId);
+        assert opId > 0 && allocator.blockForId(opId - 2) == opBlock : "cannot insert move at block boundary";
+
+        // calculate index of instruction inside instruction list of current block
+        // the minimal index (for a block with no spill moves) can be calculated because the
+        // numbering of instructions is known.
+        // When the block already contains spill moves, the index must be increased until the
+        // correct index is reached.
+        List<LIRInstruction> list = opBlock.lir().instructionsList();
+        int index = (opId - list.get(0).id()) >> 1;
+        assert list.get(index).id() <= opId : "error in calculation";
+
+        while (list.get(index).id() != opId) {
+            index++;
+            assert 0 <= index && index < list.size() : "index out of bounds";
+        }
+        assert 1 <= index && index < list.size() : "index out of bounds";
+        assert list.get(index).id() == opId : "error in calculation";
+
+        // insert new instruction before instruction at position index
+        moveResolver.moveInsertPosition(opBlock.lir(), index - 1);
+        moveResolver.addMapping(srcIt, dstIt);
+    }
+
+    int findOptimalSplitPos(LIRBlock minBlock, LIRBlock maxBlock, int maxSplitPos) {
+        int fromBlockNr = minBlock.linearScanNumber();
+        int toBlockNr = maxBlock.linearScanNumber();
+
+        assert 0 <= fromBlockNr && fromBlockNr < blockCount() : "out of range";
+        assert 0 <= toBlockNr && toBlockNr < blockCount() : "out of range";
+        assert fromBlockNr < toBlockNr : "must cross block boundary";
+
+        // Try to split at end of maxBlock. If this would be after
+        // maxSplitPos, then use the begin of maxBlock
+        int optimalSplitPos = maxBlock.lastLirInstructionId() + 2;
+        if (optimalSplitPos > maxSplitPos) {
+            optimalSplitPos = maxBlock.firstLirInstructionId();
+        }
+
+        int minLoopDepth = maxBlock.loopDepth();
+        for (int i = toBlockNr - 1; i >= fromBlockNr; i--) {
+            LIRBlock cur = blockAt(i);
+
+            if (cur.loopDepth() < minLoopDepth) {
+                // block with lower loop-depth found . split at the end of this block
+                minLoopDepth = cur.loopDepth();
+                optimalSplitPos = cur.lastLirInstructionId() + 2;
+            }
+        }
+        assert optimalSplitPos > allocator.maxOpId() || allocator.isBlockBegin(optimalSplitPos) : "algorithm must move split pos to block boundary";
+
+        return optimalSplitPos;
+    }
+
+    int findOptimalSplitPos(Interval interval, int minSplitPos, int maxSplitPos, boolean doLoopOptimization) {
+        int optimalSplitPos = -1;
+        if (minSplitPos == maxSplitPos) {
+            // trivial case, no optimization of split position possible
+            if (GraalOptions.TraceLinearScanLevel >= 4) {
+                TTY.println("      min-pos and max-pos are equal, no optimization possible");
+            }
+            optimalSplitPos = minSplitPos;
+
+        } else {
+            assert minSplitPos < maxSplitPos : "must be true then";
+            assert minSplitPos > 0 : "cannot access minSplitPos - 1 otherwise";
+
+            // reason for using minSplitPos - 1: when the minimal split pos is exactly at the
+            // beginning of a block, then minSplitPos is also a possible split position.
+            // Use the block before as minBlock, because then minBlock.lastLirInstructionId() + 2 == minSplitPos
+            LIRBlock minBlock = allocator.blockForId(minSplitPos - 1);
+
+            // reason for using maxSplitPos - 1: otherwise there would be an assert on failure
+            // when an interval ends at the end of the last block of the method
+            // (in this case, maxSplitPos == allocator().maxLirOpId() + 2, and there is no
+            // block at this opId)
+            LIRBlock maxBlock = allocator.blockForId(maxSplitPos - 1);
+
+            assert minBlock.linearScanNumber() <= maxBlock.linearScanNumber() : "invalid order";
+            if (minBlock == maxBlock) {
+                // split position cannot be moved to block boundary : so split as late as possible
+                if (GraalOptions.TraceLinearScanLevel >= 4) {
+                    TTY.println("      cannot move split pos to block boundary because minPos and maxPos are in same block");
+                }
+                optimalSplitPos = maxSplitPos;
+
+            } else {
+                if (interval.hasHoleBetween(maxSplitPos - 1, maxSplitPos) && !allocator.isBlockBegin(maxSplitPos)) {
+                    // Do not move split position if the interval has a hole before maxSplitPos.
+                    // Intervals resulting from Phi-Functions have more than one definition (marked
+                    // as mustHaveRegister) with a hole before each definition. When the register is needed
+                    // for the second definition : an earlier reloading is unnecessary.
+                    if (GraalOptions.TraceLinearScanLevel >= 4) {
+                        TTY.println("      interval has hole just before maxSplitPos, so splitting at maxSplitPos");
+                    }
+                    optimalSplitPos = maxSplitPos;
+
+                } else {
+                    // seach optimal block boundary between minSplitPos and maxSplitPos
+                    if (GraalOptions.TraceLinearScanLevel >= 4) {
+                        TTY.println("      moving split pos to optimal block boundary between block B%d and B%d", minBlock.blockID(), maxBlock.blockID());
+                    }
+
+                    if (doLoopOptimization) {
+                        // Loop optimization: if a loop-end marker is found between min- and max-position :
+                        // then split before this loop
+                        int loopEndPos = interval.nextUsageExact(RegisterPriority.LiveAtLoopEnd, minBlock.lastLirInstructionId() + 2);
+                        if (GraalOptions.TraceLinearScanLevel >= 4) {
+                            TTY.println("      loop optimization: loop end found at pos %d", loopEndPos);
+                        }
+
+                        assert loopEndPos > minSplitPos : "invalid order";
+                        if (loopEndPos < maxSplitPos) {
+                            // loop-end marker found between min- and max-position
+                            // if it is not the end marker for the same loop as the min-position : then move
+                            // the max-position to this loop block.
+                            // Desired result: uses tagged as shouldHaveRegister inside a loop cause a reloading
+                            // of the interval (normally, only mustHaveRegister causes a reloading)
+                            LIRBlock loopBlock = allocator.blockForId(loopEndPos);
+
+                            if (GraalOptions.TraceLinearScanLevel >= 4) {
+                                TTY.println("      interval is used in loop that ends in block B%d, so trying to move maxBlock back from B%d to B%d", loopBlock.blockID(), maxBlock.blockID(), loopBlock.blockID());
+                            }
+                            assert loopBlock != minBlock : "loopBlock and minBlock must be different because block boundary is needed between";
+
+                            optimalSplitPos = findOptimalSplitPos(minBlock, loopBlock, loopBlock.lastLirInstructionId() + 2);
+                            if (optimalSplitPos == loopBlock.lastLirInstructionId() + 2) {
+                                optimalSplitPos = -1;
+                                if (GraalOptions.TraceLinearScanLevel >= 4) {
+                                    TTY.println("      loop optimization not necessary");
+                                }
+                            } else {
+                                if (GraalOptions.TraceLinearScanLevel >= 4) {
+                                    TTY.println("      loop optimization successful");
+                                }
+                            }
+                        }
+                    }
+
+                    if (optimalSplitPos == -1) {
+                        // not calculated by loop optimization
+                        optimalSplitPos = findOptimalSplitPos(minBlock, maxBlock, maxSplitPos);
+                    }
+                }
+            }
+        }
+        if (GraalOptions.TraceLinearScanLevel >= 4) {
+            TTY.println("      optimal split position: %d", optimalSplitPos);
+        }
+
+        return optimalSplitPos;
+    }
+
+    // split an interval at the optimal position between minSplitPos and
+    // maxSplitPos in two parts:
+    // 1) the left part has already a location assigned
+    // 2) the right part is sorted into to the unhandled-list
+    void splitBeforeUsage(Interval interval, int minSplitPos, int maxSplitPos) {
+        if (GraalOptions.TraceLinearScanLevel >= 2) {
+            TTY.println("----- splitting interval: ");
+        }
+        if (GraalOptions.TraceLinearScanLevel >= 4) {
+            TTY.println(interval.logString(allocator));
+        }
+        if (GraalOptions.TraceLinearScanLevel >= 2) {
+            TTY.println("      between %d and %d", minSplitPos, maxSplitPos);
+        }
+
+        assert interval.from() < minSplitPos : "cannot split at start of interval";
+        assert currentPosition < minSplitPos : "cannot split before current position";
+        assert minSplitPos <= maxSplitPos : "invalid order";
+        assert maxSplitPos <= interval.to() : "cannot split after end of interval";
+
+        int optimalSplitPos = findOptimalSplitPos(interval, minSplitPos, maxSplitPos, true);
+
+        assert minSplitPos <= optimalSplitPos && optimalSplitPos <= maxSplitPos : "out of range";
+        assert optimalSplitPos <= interval.to() : "cannot split after end of interval";
+        assert optimalSplitPos > interval.from() : "cannot split at start of interval";
+
+        if (optimalSplitPos == interval.to() && interval.nextUsage(RegisterPriority.MustHaveRegister, minSplitPos) == Integer.MAX_VALUE) {
+            // the split position would be just before the end of the interval
+            // . no split at all necessary
+            if (GraalOptions.TraceLinearScanLevel >= 4) {
+                TTY.println("      no split necessary because optimal split position is at end of interval");
+            }
+            return;
+        }
+
+        // must calculate this before the actual split is performed and before split position is moved to odd opId
+        boolean moveNecessary = !allocator.isBlockBegin(optimalSplitPos) && !interval.hasHoleBetween(optimalSplitPos - 1, optimalSplitPos);
+
+        if (!allocator.isBlockBegin(optimalSplitPos)) {
+            // move position before actual instruction (odd opId)
+            optimalSplitPos = (optimalSplitPos - 1) | 1;
+        }
+
+        if (GraalOptions.TraceLinearScanLevel >= 4) {
+            TTY.println("      splitting at position %d", optimalSplitPos);
+        }
+        assert allocator.isBlockBegin(optimalSplitPos) || (optimalSplitPos % 2 == 1) : "split pos must be odd when not on block boundary";
+        assert !allocator.isBlockBegin(optimalSplitPos) || (optimalSplitPos % 2 == 0) : "split pos must be even on block boundary";
+
+        Interval splitPart = interval.split(optimalSplitPos, allocator);
+
+        allocator.copyRegisterFlags(interval, splitPart);
+        splitPart.setInsertMoveWhenActivated(moveNecessary);
+
+        assert splitPart.from() >= current.currentFrom() : "cannot append new interval before current walk position";
+        unhandledLists.addToListSortedByStartAndUsePositions(RegisterBinding.Any, splitPart);
+
+        if (GraalOptions.TraceLinearScanLevel >= 2) {
+            TTY.println("      split interval in two parts (insertMoveWhenActivated: %b)", moveNecessary);
+        }
+        if (GraalOptions.TraceLinearScanLevel >= 2) {
+            TTY.print("      ");
+            TTY.println(interval.logString(allocator));
+            TTY.print("      ");
+            TTY.println(splitPart.logString(allocator));
+        }
+    }
+
+// split an interval at the optimal position between minSplitPos and
+// maxSplitPos in two parts:
+// 1) the left part has already a location assigned
+// 2) the right part is always on the stack and therefore ignored in further processing
+
+    void splitForSpilling(Interval interval) {
+        // calculate allowed range of splitting position
+        int maxSplitPos = currentPosition;
+        int minSplitPos = Math.max(interval.previousUsage(RegisterPriority.ShouldHaveRegister, maxSplitPos) + 1, interval.from());
+
+        if (GraalOptions.TraceLinearScanLevel >= 2) {
+            TTY.print("----- splitting and spilling interval: ");
+            TTY.println(interval.logString(allocator));
+            TTY.println("      between %d and %d", minSplitPos, maxSplitPos);
+        }
+
+        assert interval.state == State.Active : "why spill interval that is not active?";
+        assert interval.from() <= minSplitPos : "cannot split before start of interval";
+        assert minSplitPos <= maxSplitPos : "invalid order";
+        assert maxSplitPos < interval.to() : "cannot split at end end of interval";
+        assert currentPosition < interval.to() : "interval must not end before current position";
+
+        if (minSplitPos == interval.from()) {
+            // the whole interval is never used, so spill it entirely to memory
+            if (GraalOptions.TraceLinearScanLevel >= 2) {
+                TTY.println("      spilling entire interval because split pos is at beginning of interval");
+                TTY.println("      use positions: " + interval.usePosList().size());
+            }
+            assert interval.firstUsage(RegisterPriority.ShouldHaveRegister) > currentPosition : "interval must not have use position before currentPosition";
+
+            allocator.assignSpillSlot(interval);
+            allocator.changeSpillState(interval, minSplitPos);
+
+            // Also kick parent intervals out of register to memory when they have no use
+            // position. This avoids short interval in register surrounded by intervals in
+            // memory . avoid useless moves from memory to register and back
+            Interval parent = interval;
+            while (parent != null && parent.isSplitChild()) {
+                parent = parent.getSplitChildBeforeOpId(parent.from());
+
+                if (parent.location().isRegister()) {
+                    if (parent.firstUsage(RegisterPriority.ShouldHaveRegister) == Integer.MAX_VALUE) {
+                        // parent is never used, so kick it out of its assigned register
+                        if (GraalOptions.TraceLinearScanLevel >= 4) {
+                            TTY.println("      kicking out interval %d out of its register because it is never used", parent.operandNumber);
+                        }
+                        allocator.assignSpillSlot(parent);
+                    } else {
+                        // do not go further back because the register is actually used by the interval
+                        parent = null;
+                    }
+                }
+            }
+
+        } else {
+            // search optimal split pos, split interval and spill only the right hand part
+            int optimalSplitPos = findOptimalSplitPos(interval, minSplitPos, maxSplitPos, false);
+
+            assert minSplitPos <= optimalSplitPos && optimalSplitPos <= maxSplitPos : "out of range";
+            assert optimalSplitPos < interval.to() : "cannot split at end of interval";
+            assert optimalSplitPos >= interval.from() : "cannot split before start of interval";
+
+            if (!allocator.isBlockBegin(optimalSplitPos)) {
+                // move position before actual instruction (odd opId)
+                optimalSplitPos = (optimalSplitPos - 1) | 1;
+            }
+
+            if (GraalOptions.TraceLinearScanLevel >= 4) {
+                TTY.println("      splitting at position %d", optimalSplitPos);
+            }
+            assert allocator.isBlockBegin(optimalSplitPos) || (optimalSplitPos % 2 == 1) : "split pos must be odd when not on block boundary";
+            assert !allocator.isBlockBegin(optimalSplitPos) || (optimalSplitPos % 2 == 0) : "split pos must be even on block boundary";
+
+            Interval spilledPart = interval.split(optimalSplitPos, allocator);
+            allocator.assignSpillSlot(spilledPart);
+            allocator.changeSpillState(spilledPart, optimalSplitPos);
+
+            if (!allocator.isBlockBegin(optimalSplitPos)) {
+                if (GraalOptions.TraceLinearScanLevel >= 4) {
+                    TTY.println("      inserting move from interval %d to %d", interval.operandNumber, spilledPart.operandNumber);
+                }
+                insertMove(optimalSplitPos, interval, spilledPart);
+            }
+
+            // the currentSplitChild is needed later when moves are inserted for reloading
+            assert spilledPart.currentSplitChild() == interval : "overwriting wrong currentSplitChild";
+            spilledPart.makeCurrentSplitChild();
+
+            if (GraalOptions.TraceLinearScanLevel >= 2) {
+                TTY.println("      split interval in two parts");
+                TTY.print("      ");
+                TTY.println(interval.logString(allocator));
+                TTY.print("      ");
+                TTY.println(spilledPart.logString(allocator));
+            }
+        }
+    }
+
+    void splitStackInterval(Interval interval) {
+        int minSplitPos = currentPosition + 1;
+        int maxSplitPos = Math.min(interval.firstUsage(RegisterPriority.ShouldHaveRegister), interval.to());
+
+        splitBeforeUsage(interval, minSplitPos, maxSplitPos);
+    }
+
+    void splitWhenPartialRegisterAvailable(Interval interval, int registerAvailableUntil) {
+        int minSplitPos = Math.max(interval.previousUsage(RegisterPriority.ShouldHaveRegister, registerAvailableUntil), interval.from() + 1);
+        splitBeforeUsage(interval, minSplitPos, registerAvailableUntil);
+    }
+
+    void splitAndSpillInterval(Interval interval) {
+        assert interval.state == State.Active || interval.state == State.Inactive : "other states not allowed";
+
+        int currentPos = currentPosition;
+        if (interval.state == State.Inactive) {
+            // the interval is currently inactive, so no spill slot is needed for now.
+            // when the split part is activated, the interval has a new chance to get a register,
+            // so in the best case no stack slot is necessary
+            assert interval.hasHoleBetween(currentPos - 1, currentPos + 1) : "interval can not be inactive otherwise";
+            splitBeforeUsage(interval, currentPos + 1, currentPos + 1);
+
+        } else {
+            // search the position where the interval must have a register and split
+            // at the optimal position before.
+            // The new created part is added to the unhandled list and will get a register
+            // when it is activated
+            int minSplitPos = currentPos + 1;
+            int maxSplitPos = Math.min(interval.nextUsage(RegisterPriority.MustHaveRegister, minSplitPos), interval.to());
+
+            splitBeforeUsage(interval, minSplitPos, maxSplitPos);
+
+            assert interval.nextUsage(RegisterPriority.MustHaveRegister, currentPos) == Integer.MAX_VALUE : "the remaining part is spilled to stack and therefore has no register";
+            splitForSpilling(interval);
+        }
+    }
+
+    boolean allocFreeRegister(Interval interval) {
+        if (GraalOptions.TraceLinearScanLevel >= 2) {
+            TTY.println("trying to find free register for " + interval.logString(allocator));
+        }
+
+        initUseLists(true);
+        freeExcludeActiveFixed();
+        freeExcludeActiveAny();
+        freeCollectInactiveFixed(interval);
+        freeCollectInactiveAny(interval);
+        // freeCollectUnhandled(fixedKind, cur);
+        assert unhandledLists.get(RegisterBinding.Fixed) == Interval.EndMarker : "must not have unhandled fixed intervals because all fixed intervals have a use at position 0";
+
+        // usePos contains the start of the next interval that has this register assigned
+        // (either as a fixed register or a normal allocated register in the past)
+        // only intervals overlapping with cur are processed, non-overlapping invervals can be ignored safely
+        if (GraalOptions.TraceLinearScanLevel >= 4) {
+            TTY.println("      state of registers:");
+            for (CiRegister register : availableRegs) {
+                int i = register.number;
+                TTY.println("      reg %d: usePos: %d", register.number, usePos[i]);
+            }
+        }
+
+        CiRegister hint = null;
+        Interval locationHint = interval.locationHint(true, allocator);
+        if (locationHint != null && locationHint.location() != null && locationHint.location().isRegister()) {
+            hint = locationHint.location().asRegister();
+            if (GraalOptions.TraceLinearScanLevel >= 4) {
+                TTY.println("      hint register %d from interval %s", hint.number, locationHint.logString(allocator));
+            }
+        }
+        assert interval.location() == null : "register already assigned to interval";
+
+        // the register must be free at least until this position
+        int regNeededUntil = interval.from() + 1;
+        int intervalTo = interval.to();
+
+        boolean needSplit = false;
+        int splitPos = -1;
+
+        CiRegister reg = null;
+        CiRegister minFullReg = null;
+        CiRegister maxPartialReg = null;
+
+        for (int i = 0; i < availableRegs.length; ++i) {
+            CiRegister availableReg = availableRegs[i];
+            int number = availableReg.number;
+            if (usePos[number] >= intervalTo) {
+                // this register is free for the full interval
+                if (minFullReg == null || availableReg == hint || (usePos[number] < usePos[minFullReg.number] && minFullReg != hint)) {
+                    minFullReg = availableReg;
+                }
+            } else if (usePos[number] > regNeededUntil) {
+                // this register is at least free until regNeededUntil
+                if (maxPartialReg == null || availableReg == hint || (usePos[number] > usePos[maxPartialReg.number] && maxPartialReg != hint)) {
+                    maxPartialReg = availableReg;
+                }
+            }
+        }
+
+        if (minFullReg != null) {
+            reg = minFullReg;
+        } else if (maxPartialReg != null) {
+            needSplit = true;
+            reg = maxPartialReg;
+        } else {
+            return false;
+        }
+
+        splitPos = usePos[reg.number];
+        interval.assignLocation(reg.asValue(interval.kind()));
+        if (GraalOptions.TraceLinearScanLevel >= 2) {
+            TTY.println("selected register %d", reg.number);
+        }
+
+        assert splitPos > 0 : "invalid splitPos";
+        if (needSplit) {
+            // register not available for full interval, so split it
+            splitWhenPartialRegisterAvailable(interval, splitPos);
+        }
+
+        // only return true if interval is completely assigned
+        return true;
+    }
+
+    CiRegister findLockedRegister(int regNeededUntil, int intervalTo, CiValue ignoreReg, boolean[] needSplit) {
+        int maxReg = -1;
+        CiRegister ignore = ignoreReg.isRegister() ? ignoreReg.asRegister() : null;
+
+        for (CiRegister reg : availableRegs) {
+            int i = reg.number;
+            if (reg == ignore) {
+                // this register must be ignored
+
+            } else if (usePos[i] > regNeededUntil) {
+                if (maxReg == -1 || (usePos[i] > usePos[maxReg])) {
+                    maxReg = i;
+                }
+            }
+        }
+
+        if (maxReg != -1) {
+            if (blockPos[maxReg] <= intervalTo) {
+                needSplit[0] = true;
+            }
+            return availableRegs[maxReg];
+        }
+
+        return null;
+    }
+
+    void splitAndSpillIntersectingIntervals(CiRegister reg) {
+        assert reg != null : "no register assigned";
+
+        for (int i = 0; i < spillIntervals[reg.number].size(); i++) {
+            Interval interval = spillIntervals[reg.number].get(i);
+            removeFromList(interval);
+            splitAndSpillInterval(interval);
+        }
+    }
+
+    // Split an Interval and spill it to memory so that cur can be placed in a register
+    void allocLockedRegister(Interval interval) {
+        if (GraalOptions.TraceLinearScanLevel >= 2) {
+            TTY.println("need to split and spill to get register for " + interval.logString(allocator));
+        }
+
+        // collect current usage of registers
+        initUseLists(false);
+        spillExcludeActiveFixed();
+        //  spillBlockUnhandledFixed(cur);
+        assert unhandledLists.get(RegisterBinding.Fixed) == Interval.EndMarker : "must not have unhandled fixed intervals because all fixed intervals have a use at position 0";
+        spillBlockInactiveFixed(interval);
+        spillCollectActiveAny();
+        spillCollectInactiveAny(interval);
+
+        if (GraalOptions.TraceLinearScanLevel >= 4) {
+            TTY.println("      state of registers:");
+            for (CiRegister reg : availableRegs) {
+                int i = reg.number;
+                TTY.print("      reg %d: usePos: %d, blockPos: %d, intervals: ", i, usePos[i], blockPos[i]);
+                for (int j = 0; j < spillIntervals[i].size(); j++) {
+                    TTY.print("%d ", spillIntervals[i].get(j).operandNumber);
+                }
+                TTY.println();
+            }
+        }
+
+        // the register must be free at least until this position
+        int firstUsage = interval.firstUsage(RegisterPriority.MustHaveRegister);
+        int regNeededUntil = Math.min(firstUsage, interval.from() + 1);
+        int intervalTo = interval.to();
+        assert regNeededUntil > 0 && regNeededUntil < Integer.MAX_VALUE : "interval has no use";
+
+        CiRegister reg = null;
+        CiRegister ignore = interval.location() != null && interval.location().isRegister() ? interval.location().asRegister() : null;
+        for (CiRegister availableReg : availableRegs) {
+            int number = availableReg.number;
+            if (availableReg == ignore) {
+                // this register must be ignored
+            } else if (usePos[number] > regNeededUntil) {
+                if (reg == null || (usePos[number] > usePos[reg.number])) {
+                    reg = availableReg;
+                }
+            }
+        }
+
+        if (reg == null || usePos[reg.number] <= firstUsage) {
+            // the first use of cur is later than the spilling position -> spill cur
+            if (GraalOptions.TraceLinearScanLevel >= 4) {
+                TTY.println("able to spill current interval. firstUsage(register): %d, usePos: %d", firstUsage, reg == null ? 0 : usePos[reg.number]);
+            }
+
+            if (firstUsage <= interval.from() + 1) {
+                assert false : "cannot spill interval that is used in first instruction (possible reason: no register found) firstUsage=" + firstUsage + ", interval.from()=" + interval.from();
+                // assign a reasonable register and do a bailout in product mode to avoid errors
+                allocator.assignSpillSlot(interval);
+                throw new CiBailout("LinearScan: no register found");
+            }
+
+            splitAndSpillInterval(interval);
+            return;
+        }
+
+        boolean needSplit = blockPos[reg.number] <= intervalTo;
+
+        int splitPos = blockPos[reg.number];
+
+        if (GraalOptions.TraceLinearScanLevel >= 4) {
+            TTY.println("decided to use register %d", reg.number);
+        }
+        assert splitPos > 0 : "invalid splitPos";
+        assert needSplit || splitPos > interval.from() : "splitting interval at from";
+
+        interval.assignLocation(reg.asValue(interval.kind()));
+        if (needSplit) {
+            // register not available for full interval :  so split it
+            splitWhenPartialRegisterAvailable(interval, splitPos);
+        }
+
+        // perform splitting and spilling for all affected intervals
+        splitAndSpillIntersectingIntervals(reg);
+    }
+
+    boolean noAllocationPossible(Interval interval) {
+
+        if (compilation.target.arch.isX86()) {
+            // fast calculation of intervals that can never get a register because the
+            // the next instruction is a call that blocks all registers
+            // Note: this does not work if callee-saved registers are available (e.g. on Sparc)
+
+            // check if this interval is the result of a split operation
+            // (an interval got a register until this position)
+            int pos = interval.from();
+            if (isOdd(pos)) {
+                // the current instruction is a call that blocks all registers
+                if (pos < allocator.maxOpId() && allocator.hasCall(pos + 1) && interval.to() > pos + 1) {
+                    if (GraalOptions.TraceLinearScanLevel >= 4) {
+                        TTY.println("      free register cannot be available because all registers blocked by following call");
+                    }
+
+                    // safety check that there is really no register available
+                    assert !allocFreeRegister(interval) : "found a register for this interval";
+                    return true;
+                }
+
+            }
+        }
+        return false;
+    }
+
+    void initVarsForAlloc(Interval interval) {
+        EnumMap<RegisterFlag, CiRegister[]> categorizedRegs = allocator.compilation.registerConfig.getCategorizedAllocatableRegisters();
+        if (allocator.operands.mustBeByteRegister(interval.operand)) {
+            assert interval.kind() != CiKind.Float && interval.kind() != CiKind.Double : "cpu regs only";
+            availableRegs = categorizedRegs.get(RegisterFlag.Byte);
+        } else if (interval.kind() == CiKind.Float || interval.kind() == CiKind.Double) {
+            availableRegs = categorizedRegs.get(RegisterFlag.FPU);
+        } else {
+            availableRegs = categorizedRegs.get(RegisterFlag.CPU);
+        }
+    }
+
+    boolean isMove(LIRInstruction op, Interval from, Interval to) {
+        if (op.code != LIROpcode.Move) {
+            return false;
+        }
+        assert op instanceof LIROp1 : "move must be LIROp1";
+
+        CiValue input = ((LIROp1) op).operand();
+        CiValue result = ((LIROp1) op).result();
+        return input.isVariable() && result.isVariable() && input == from.operand && result == to.operand;
+    }
+
+    // optimization (especially for phi functions of nested loops):
+    // assign same spill slot to non-intersecting intervals
+    void combineSpilledIntervals(Interval interval) {
+        if (interval.isSplitChild()) {
+            // optimization is only suitable for split parents
+            return;
+        }
+
+        Interval registerHint = interval.locationHint(false, allocator);
+        if (registerHint == null) {
+            // cur is not the target of a move : otherwise registerHint would be set
+            return;
+        }
+        assert registerHint.isSplitParent() : "register hint must be split parent";
+
+        if (interval.spillState() != SpillState.NoOptimization || registerHint.spillState() != SpillState.NoOptimization) {
+            // combining the stack slots for intervals where spill move optimization is applied
+            // is not benefitial and would cause problems
+            return;
+        }
+
+        int beginPos = interval.from();
+        int endPos = interval.to();
+        if (endPos > allocator.maxOpId() || isOdd(beginPos) || isOdd(endPos)) {
+            // safety check that lirOpWithId is allowed
+            return;
+        }
+
+        if (!isMove(allocator.instructionForId(beginPos), registerHint, interval) || !isMove(allocator.instructionForId(endPos), interval, registerHint)) {
+            // cur and registerHint are not connected with two moves
+            return;
+        }
+
+        Interval beginHint = registerHint.getSplitChildAtOpId(beginPos, LIRInstruction.OperandMode.Input, allocator);
+        Interval endHint = registerHint.getSplitChildAtOpId(endPos, LIRInstruction.OperandMode.Output, allocator);
+        if (beginHint == endHint || beginHint.to() != beginPos || endHint.from() != endPos) {
+            // registerHint must be split : otherwise the re-writing of use positions does not work
+            return;
+        }
+
+        assert beginHint.location() != null : "must have register assigned";
+        assert endHint.location() == null : "must not have register assigned";
+        assert interval.firstUsage(RegisterPriority.MustHaveRegister) == beginPos : "must have use position at begin of interval because of move";
+        assert endHint.firstUsage(RegisterPriority.MustHaveRegister) == endPos : "must have use position at begin of interval because of move";
+
+        if (beginHint.location().isRegister()) {
+            // registerHint is not spilled at beginPos : so it would not be benefitial to immediately spill cur
+            return;
+        }
+        assert registerHint.spillSlot() != null : "must be set when part of interval was spilled";
+
+        // modify intervals such that cur gets the same stack slot as registerHint
+        // delete use positions to prevent the intervals to get a register at beginning
+        interval.setSpillSlot(registerHint.spillSlot());
+        interval.removeFirstUsePos();
+        endHint.removeFirstUsePos();
+    }
+
+    // allocate a physical register or memory location to an interval
+    @Override
+    boolean activateCurrent() {
+        Interval interval = current;
+        boolean result = true;
+
+        if (GraalOptions.TraceLinearScanLevel >= 2) {
+            TTY.println("+++++ activating interval " + interval.logString(allocator));
+        }
+
+        if (GraalOptions.TraceLinearScanLevel >= 4) {
+            TTY.println("      splitParent: %s, insertMoveWhenActivated: %b", interval.splitParent().operandNumber, interval.insertMoveWhenActivated());
+        }
+
+        final CiValue operand = interval.operand;
+        if (interval.location() != null && interval.location().isStackSlot()) {
+            // activating an interval that has a stack slot assigned . split it at first use position
+            // used for method parameters
+            if (GraalOptions.TraceLinearScanLevel >= 4) {
+                TTY.println("      interval has spill slot assigned (method parameter) . split it before first use");
+            }
+            splitStackInterval(interval);
+            result = false;
+
+        } else {
+            if (operand.isVariable() && allocator.operands.mustStartInMemory((CiVariable) operand)) {
+                assert interval.location() == null : "register already assigned";
+                allocator.assignSpillSlot(interval);
+
+                if (!allocator.operands.mustStayInMemory((CiVariable) operand)) {
+                    // activating an interval that must start in a stack slot but may get a register later
+                    // used for lirRoundfp: rounding is done by store to stack and reload later
+                    if (GraalOptions.TraceLinearScanLevel >= 4) {
+                        TTY.println("      interval must start in stack slot . split it before first use");
+                    }
+                    splitStackInterval(interval);
+                }
+
+                result = false;
+            } else if (interval.location() == null) {
+                // interval has not assigned register . normal allocation
+                // (this is the normal case for most intervals)
+                if (GraalOptions.TraceLinearScanLevel >= 4) {
+                    TTY.println("      normal allocation of register");
+                }
+
+                // assign same spill slot to non-intersecting intervals
+                combineSpilledIntervals(interval);
+
+                initVarsForAlloc(interval);
+                if (noAllocationPossible(interval) || !allocFreeRegister(interval)) {
+                    // no empty register available.
+                    // split and spill another interval so that this interval gets a register
+                    allocLockedRegister(interval);
+                }
+
+                // spilled intervals need not be move to active-list
+                if (!interval.location().isRegister()) {
+                    result = false;
+                }
+            }
+        }
+
+        // load spilled values that become active from stack slot to register
+        if (interval.insertMoveWhenActivated()) {
+            assert interval.isSplitChild();
+            assert interval.currentSplitChild() != null;
+            assert interval.currentSplitChild().operand != operand : "cannot insert move between same interval";
+            if (GraalOptions.TraceLinearScanLevel >= 4) {
+                TTY.println("Inserting move from interval %d to %d because insertMoveWhenActivated is set", interval.currentSplitChild().operandNumber, interval.operandNumber);
+            }
+
+            insertMove(interval.from(), interval.currentSplitChild(), interval);
+        }
+        interval.makeCurrentSplitChild();
+
+        return result; // true = interval is moved to active list
+    }
+
+    public void finishAllocation() {
+        // must be called when all intervals are allocated
+        moveResolver.resolveAndAppendMoves();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/MoveResolver.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.alloc;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.lir.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.sun.cri.ci.*;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+final class MoveResolver {
+
+    private final LinearScan allocator;
+
+    private LIRList insertList;
+    private int insertIdx;
+    private LIRInsertionBuffer insertionBuffer; // buffer where moves are inserted
+
+    private final List<Interval> mappingFrom;
+    private final List<CiValue> mappingFromOpr;
+    private final List<Interval> mappingTo;
+    private boolean multipleReadsAllowed;
+    private final int[] registerBlocked;
+
+    private int registerBlocked(int reg) {
+        return registerBlocked[reg];
+    }
+
+    private void setRegisterBlocked(int reg, int direction) {
+        assert direction == 1 || direction == -1 : "out of bounds";
+        registerBlocked[reg] += direction;
+    }
+
+    void setMultipleReadsAllowed() {
+        multipleReadsAllowed = true;
+    }
+
+    boolean hasMappings() {
+        return mappingFrom.size() > 0;
+    }
+
+    MoveResolver(LinearScan allocator) {
+
+        this.allocator = allocator;
+        this.multipleReadsAllowed = false;
+        this.mappingFrom = new ArrayList<Interval>(8);
+        this.mappingFromOpr = new ArrayList<CiValue>(8);
+        this.mappingTo = new ArrayList<Interval>(8);
+        this.insertIdx = -1;
+        this.insertionBuffer = new LIRInsertionBuffer();
+        this.registerBlocked = new int[allocator.registers.length];
+        assert checkEmpty();
+    }
+
+    boolean checkEmpty() {
+        assert mappingFrom.size() == 0 && mappingFromOpr.size() == 0 && mappingTo.size() == 0 : "list must be empty before and after processing";
+        for (int i = 0; i < allocator.registers.length; i++) {
+            assert registerBlocked(i) == 0 : "register map must be empty before and after processing";
+        }
+        assert !multipleReadsAllowed : "must have default value";
+        return true;
+    }
+
+    private boolean verifyBeforeResolve() {
+        assert mappingFrom.size() == mappingFromOpr.size() : "length must be equal";
+        assert mappingFrom.size() == mappingTo.size() : "length must be equal";
+        assert insertList != null && insertIdx != -1 : "insert position not set";
+
+        int i;
+        int j;
+        if (!multipleReadsAllowed) {
+            for (i = 0; i < mappingFrom.size(); i++) {
+                for (j = i + 1; j < mappingFrom.size(); j++) {
+                    assert mappingFrom.get(i) == null || mappingFrom.get(i) != mappingFrom.get(j) : "cannot read from same interval twice";
+                }
+            }
+        }
+
+        for (i = 0; i < mappingTo.size(); i++) {
+            for (j = i + 1; j < mappingTo.size(); j++) {
+                assert mappingTo.get(i) != mappingTo.get(j) : "cannot write to same interval twice";
+            }
+        }
+
+        HashSet<CiValue> usedRegs = new HashSet<CiValue>();
+        if (!multipleReadsAllowed) {
+            for (i = 0; i < mappingFrom.size(); i++) {
+                Interval interval = mappingFrom.get(i);
+                if (interval != null) {
+                    boolean unique = usedRegs.add(interval.location());
+                    assert unique : "cannot read from same register twice";
+                }
+            }
+        }
+
+        usedRegs.clear();
+        for (i = 0; i < mappingTo.size(); i++) {
+            Interval interval = mappingTo.get(i);
+            boolean unique = usedRegs.add(interval.location());
+            assert unique : "cannot write to same register twice";
+        }
+
+        usedRegs.clear();
+        for (i = 0; i < mappingFrom.size(); i++) {
+            Interval interval = mappingFrom.get(i);
+            if (interval != null && !interval.location().isRegister()) {
+                usedRegs.add(interval.location());
+            }
+        }
+        for (i = 0; i < mappingTo.size(); i++) {
+            Interval interval = mappingTo.get(i);
+            assert !usedRegs.contains(interval.location()) || interval.location() == mappingFrom.get(i).location() : "stack slots used in mappingFrom must be disjoint to mappingTo";
+        }
+
+        return true;
+    }
+
+    // mark assignedReg and assignedRegHi of the interval as blocked
+    private void blockRegisters(Interval interval) {
+        CiValue location = interval.location();
+        if (location.isRegister()) {
+            int reg = location.asRegister().number;
+            assert multipleReadsAllowed || registerBlocked(reg) == 0 : "register already marked as used";
+            setRegisterBlocked(reg, 1);
+        }
+    }
+
+    // mark assignedReg and assignedRegHi of the interval as unblocked
+    private void unblockRegisters(Interval interval) {
+        CiValue location = interval.location();
+        if (location.isRegister()) {
+            int reg = location.asRegister().number;
+            assert registerBlocked(reg) > 0 : "register already marked as unused";
+            setRegisterBlocked(reg, -1);
+        }
+    }
+
+    /**
+     * Checks if the {@linkplain Interval#location() location} of {@code to} is not blocked
+     * or is only blocked by {@code from}.
+     */
+    private boolean safeToProcessMove(Interval from, Interval to) {
+        CiValue fromReg = from != null ? from.location() : null;
+
+        CiValue reg = to.location();
+        if (reg.isRegister()) {
+            if (registerBlocked(reg.asRegister().number) > 1 || (registerBlocked(reg.asRegister().number) == 1 && reg != fromReg)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    private void createInsertionBuffer(LIRList list) {
+        assert !insertionBuffer.initialized() : "overwriting existing buffer";
+        insertionBuffer.init(list);
+    }
+
+    private void appendInsertionBuffer() {
+        if (insertionBuffer.initialized()) {
+            insertionBuffer.lirList().append(insertionBuffer);
+        }
+        assert !insertionBuffer.initialized() : "must be uninitialized now";
+
+        insertList = null;
+        insertIdx = -1;
+    }
+
+    private void insertMove(Interval fromInterval, Interval toInterval) {
+        assert fromInterval.operand != toInterval.operand : "from and to interval equal: " + fromInterval;
+        assert Util.archKindsEqual(fromInterval.kind(), toInterval.kind()) : "move between different types";
+        assert insertList != null && insertIdx != -1 : "must setup insert position first";
+        assert insertionBuffer.lirList() == insertList : "wrong insertion buffer";
+
+        CiValue fromOpr = fromInterval.operand;
+        CiValue toOpr = toInterval.operand;
+
+        insertionBuffer.move(insertIdx, fromOpr, toOpr, null);
+
+        if (GraalOptions.TraceLinearScanLevel >= 4) {
+            TTY.println("MoveResolver: inserted move from %d (%s) to %d (%s)", fromInterval.operandNumber, fromInterval.location(), toInterval.operandNumber, toInterval.location());
+        }
+    }
+
+    private void insertMove(CiValue fromOpr, Interval toInterval) {
+        assert Util.archKindsEqual(fromOpr.kind, toInterval.kind()) : "move between different types";
+        assert insertList != null && insertIdx != -1 : "must setup insert position first";
+        assert insertionBuffer.lirList() == insertList : "wrong insertion buffer";
+
+        CiValue toOpr = toInterval.operand;
+        insertionBuffer.move(insertIdx, fromOpr, toOpr, null);
+
+        if (GraalOptions.TraceLinearScanLevel >= 4) {
+            TTY.print("MoveResolver: inserted move from constant %s to %d (%s)", fromOpr, toInterval.operandNumber, toInterval.location());
+        }
+    }
+
+    private void resolveMappings() {
+        assert verifyBeforeResolve();
+
+        // Block all registers that are used as input operands of a move.
+        // When a register is blocked, no move to this register is emitted.
+        // This is necessary for detecting cycles in moves.
+        int i;
+        for (i = mappingFrom.size() - 1; i >= 0; i--) {
+            Interval fromInterval = mappingFrom.get(i);
+            if (fromInterval != null) {
+                blockRegisters(fromInterval);
+            }
+        }
+
+        int spillCandidate = -1;
+        while (mappingFrom.size() > 0) {
+            boolean processedInterval = false;
+
+            for (i = mappingFrom.size() - 1; i >= 0; i--) {
+                Interval fromInterval = mappingFrom.get(i);
+                Interval toInterval = mappingTo.get(i);
+
+                if (safeToProcessMove(fromInterval, toInterval)) {
+                    // this interval can be processed because target is free
+                    if (fromInterval != null) {
+                        insertMove(fromInterval, toInterval);
+                        unblockRegisters(fromInterval);
+                    } else {
+                        insertMove(mappingFromOpr.get(i), toInterval);
+                    }
+                    mappingFrom.remove(i);
+                    mappingFromOpr.remove(i);
+                    mappingTo.remove(i);
+
+                    processedInterval = true;
+                } else if (fromInterval != null && fromInterval.location().isRegister()) {
+                    // this interval cannot be processed now because target is not free
+                    // it starts in a register, so it is a possible candidate for spilling
+                    spillCandidate = i;
+                }
+            }
+
+            if (!processedInterval) {
+                // no move could be processed because there is a cycle in the move list
+                // (e.g. r1 . r2, r2 . r1), so one interval must be spilled to memory
+                assert spillCandidate != -1 : "no interval in register for spilling found";
+
+                // create a new spill interval and assign a stack slot to it
+                Interval fromInterval = mappingFrom.get(spillCandidate);
+                Interval spillInterval = allocator.createDerivedInterval(fromInterval);
+                spillInterval.setKind(fromInterval.kind());
+
+                // add a dummy range because real position is difficult to calculate
+                // Note: this range is a special case when the integrity of the allocation is checked
+                spillInterval.addRange(1, 2);
+
+                // do not allocate a new spill slot for temporary interval, but
+                // use spill slot assigned to fromInterval. Otherwise moves from
+                // one stack slot to another can happen (not allowed by LIRAssembler
+                CiStackSlot spillSlot = fromInterval.spillSlot();
+                if (spillSlot == null) {
+                    spillSlot = allocator.allocateSpillSlot(spillInterval.kind());
+                    fromInterval.setSpillSlot(spillSlot);
+                }
+                spillInterval.assignLocation(spillSlot);
+
+                if (GraalOptions.TraceLinearScanLevel >= 4) {
+                    TTY.println("created new Interval %s for spilling", spillInterval.operand);
+                }
+
+                // insert a move from register to stack and update the mapping
+                insertMove(fromInterval, spillInterval);
+                mappingFrom.set(spillCandidate, spillInterval);
+                unblockRegisters(fromInterval);
+            }
+        }
+
+        // reset to default value
+        multipleReadsAllowed = false;
+
+        // check that all intervals have been processed
+        assert checkEmpty();
+    }
+
+    void setInsertPosition(LIRList insertList, int insertIdx) {
+        assert this.insertList == null && this.insertIdx == -1 : "use moveInsertPosition instead of setInsertPosition when data already set";
+
+        createInsertionBuffer(insertList);
+        this.insertList = insertList;
+        this.insertIdx = insertIdx;
+    }
+
+    void moveInsertPosition(LIRList insertList, int insertIdx) {
+        if (this.insertList != null && (this.insertList != insertList || this.insertIdx != insertIdx)) {
+            // insert position changed . resolve current mappings
+            resolveMappings();
+        }
+
+        if (this.insertList != insertList) {
+            // block changed . append insertionBuffer because it is
+            // bound to a specific block and create a new insertionBuffer
+            appendInsertionBuffer();
+            createInsertionBuffer(insertList);
+        }
+
+        this.insertList = insertList;
+        this.insertIdx = insertIdx;
+    }
+
+    void addMapping(Interval fromInterval, Interval toInterval) {
+        if (GraalOptions.TraceLinearScanLevel >= 4) {
+            TTY.println("MoveResolver: adding mapping from interval %d (%s) to interval %d (%s)", fromInterval.operandNumber, fromInterval.location(), toInterval.operandNumber, toInterval.location());
+        }
+
+        assert fromInterval.operand != toInterval.operand : "from and to interval equal: " + fromInterval;
+        assert Util.archKindsEqual(fromInterval.kind(), toInterval.kind());
+        mappingFrom.add(fromInterval);
+        mappingFromOpr.add(CiValue.IllegalValue);
+        mappingTo.add(toInterval);
+    }
+
+    void addMapping(CiValue fromOpr, Interval toInterval) {
+        if (GraalOptions.TraceLinearScanLevel >= 4) {
+            TTY.println("MoveResolver: adding mapping from %s to %d (%s)", fromOpr, toInterval.operandNumber, toInterval.location());
+        }
+        assert fromOpr.isConstant() : "only for constants";
+
+        mappingFrom.add(null);
+        mappingFromOpr.add(fromOpr);
+        mappingTo.add(toInterval);
+    }
+
+    void resolveAndAppendMoves() {
+        if (hasMappings()) {
+            resolveMappings();
+        }
+        appendInsertionBuffer();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/OperandPool.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.alloc;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+/**
+ * An ordered, 0-based indexable pool of instruction operands for a method being compiled.
+ * The physical {@linkplain CiRegister registers} of the platform occupy the front of the
+ * pool (starting at index 0) followed by {@linkplain CiVariable variable} operands.
+ * The index of an operand in the pool is its {@linkplain #operandNumber(CiValue) operand number}.
+ *
+ * In the original HotSpot C1 source code, this pool corresponds to the
+ * "flat register file" mentioned in c1_LinearScan.cpp.
+ *
+ * @author Doug Simon
+ */
+public final class OperandPool {
+
+    public static final int INITIAL_VARIABLE_CAPACITY = 20;
+
+    /**
+     * The physical registers occupying the head of the operand pool. This is the complete
+     * {@linkplain CiArchitecture#registers register set} of the target architecture, not
+     * just the allocatable registers.
+     */
+    private final CiRegister[] registers;
+
+    /**
+     * The variable operands allocated from this pool. The {@linkplain #operandNumber(CiValue) number}
+     * of the first variable operand in this pool is one greater than the number of the last
+     * register operand in the pool.
+     */
+    private final ArrayList<CiVariable> variables;
+
+    /**
+     * Map from a {@linkplain CiVariable#index variable index} to the instruction whose result is stored in the denoted variable.
+     * This map is only populated and used if {@link GraalOptions#DetailedAsserts} is {@code true}.
+     */
+    private final ArrayList<Value> variableDefs;
+
+    /**
+     * The {@linkplain #operandNumber(CiValue) number} of the first variable operand
+     * {@linkplain #newVariable(CiKind) allocated} from this pool.
+     */
+    private final int firstVariableNumber;
+
+    /**
+     * Records which variable operands have the {@link VariableFlag#MustBeByteRegister} flag set.
+     */
+    private BitMap mustBeByteRegister;
+
+    /**
+     * Records which variable operands have the {@link VariableFlag#MustStartInMemory} flag set.
+     */
+    private BitMap mustStartInMemory;
+
+    /**
+     * Records which variable operands have the {@link VariableFlag#MustStayInMemory} flag set.
+     */
+    private BitMap mustStayInMemory;
+
+    /**
+     * Flags that can be set for {@linkplain CiValue#isVariable() variable} operands.
+     */
+    public enum VariableFlag {
+        /**
+         * Denotes a variable that needs to be assigned a memory location
+         * at the beginning, but may then be loaded in a register.
+         */
+        MustStartInMemory,
+
+        /**
+         * Denotes a variable that needs to be assigned a memory location
+         * at the beginning and never subsequently loaded in a register.
+         */
+        MustStayInMemory,
+
+        /**
+         * Denotes a variable that must be assigned to a byte-sized register.
+         */
+        MustBeByteRegister;
+
+        public static final VariableFlag[] VALUES = values();
+    }
+
+    private static BitMap set(BitMap map, CiVariable variable) {
+        if (map == null) {
+            int length = BitMap.roundUpLength(variable.index + 1);
+            map = new BitMap(length);
+        } else if (map.size() <= variable.index) {
+            int length = BitMap.roundUpLength(variable.index + 1);
+            map.grow(length);
+        }
+        map.set(variable.index);
+        return map;
+    }
+
+    private static boolean get(BitMap map, CiVariable variable) {
+        if (map == null || map.size() <= variable.index) {
+            return false;
+        }
+        return map.get(variable.index);
+    }
+
+    /**
+     * Creates a new operand pool.
+     *
+     * @param target description of the target architecture for a compilation
+     */
+    public OperandPool(CiTarget target) {
+        CiRegister[] registers = target.arch.registers;
+        this.firstVariableNumber = registers.length;
+        this.registers = registers;
+        variables = new ArrayList<CiVariable>(INITIAL_VARIABLE_CAPACITY);
+        variableDefs = GraalOptions.DetailedAsserts ? new ArrayList<Value>(INITIAL_VARIABLE_CAPACITY) : null;
+    }
+
+    /**
+     * Creates a new {@linkplain CiVariable variable} operand.
+     *
+     * @param kind the kind of the variable
+     * @return a new variable
+     */
+    public CiVariable newVariable(CiKind kind) {
+        return newVariable(kind, kind == CiKind.Boolean || kind == CiKind.Byte ? VariableFlag.MustBeByteRegister : null);
+    }
+
+    /**
+     * Creates a new {@linkplain CiVariable variable} operand.
+     *
+     * @param kind the kind of the variable
+     * @param flag a flag that is set for the new variable operand (ignored if {@code null})
+     * @return a new variable operand
+     */
+    public CiVariable newVariable(CiKind kind, VariableFlag flag) {
+        assert kind != CiKind.Void;
+        int varIndex = variables.size();
+        CiVariable var = CiVariable.get(kind, varIndex);
+        if (flag == VariableFlag.MustBeByteRegister) {
+            mustBeByteRegister = set(mustBeByteRegister, var);
+        } else if (flag == VariableFlag.MustStartInMemory) {
+            mustStartInMemory = set(mustStartInMemory, var);
+        } else if (flag == VariableFlag.MustStayInMemory) {
+            mustStayInMemory = set(mustStayInMemory, var);
+        } else {
+            assert flag == null;
+        }
+        variables.add(var);
+        return var;
+    }
+
+    /**
+     * Gets the unique number for an operand contained in this pool.
+     *
+     *
+     * @param operand an operand
+     * @return the unique number for {@code operand} in the range {@code [0 .. size())}
+     */
+    public int operandNumber(CiValue operand) {
+        if (operand.isRegister()) {
+            int number = operand.asRegister().number;
+            assert number < firstVariableNumber;
+            return number;
+        }
+        assert operand.isVariable();
+        return firstVariableNumber + ((CiVariable) operand).index;
+    }
+
+    /**
+     * Gets the operand in this pool denoted by a given operand number.
+     *
+     * @param operandNumber a value that must be in the range {@code [0 .. size())}
+     * @return the operand in this pool denoted by {@code operandNumber}
+     */
+    public CiValue operandFor(int operandNumber) {
+        if (operandNumber < firstVariableNumber) {
+            assert operandNumber >= 0;
+            return registers[operandNumber].asValue();
+        }
+        int index = operandNumber - firstVariableNumber;
+        CiVariable variable = variables.get(index);
+        assert variable.index == index;
+        return variable;
+    }
+
+    /**
+     * Records that the result of {@code instruction} is stored in {@code result}.
+     *
+     * @param result the variable storing the result of {@code instruction}
+     * @param instruction an instruction that produces a result (i.e. pushes a value to the stack)
+     */
+    public void recordResult(CiVariable result, Value instruction) {
+        while (variableDefs.size() <= result.index) {
+            variableDefs.add(null);
+        }
+        variableDefs.set(result.index, instruction);
+    }
+
+    /**
+     * Gets the instruction whose result is recorded in a given variable.
+     *
+     * @param result the variable storing the result of an instruction
+     * @return the instruction that stores its result in {@code result}
+     */
+    public Value instructionForResult(CiVariable result) {
+        if (variableDefs.size() > result.index) {
+            return variableDefs.get(result.index);
+        }
+        return null;
+    }
+
+    public boolean mustStartInMemory(CiVariable operand) {
+        return get(mustStartInMemory, operand) || get(mustStayInMemory, operand);
+    }
+
+    public boolean mustStayInMemory(CiVariable operand) {
+        return get(mustStayInMemory, operand);
+    }
+
+    public boolean mustBeByteRegister(CiValue operand) {
+        return get(mustBeByteRegister, (CiVariable) operand);
+    }
+
+    public void setMustBeByteRegister(CiVariable operand) {
+        mustBeByteRegister = set(mustBeByteRegister, operand);
+    }
+
+    /**
+     * Gets the number of operands in this pool. This value will increase by 1 for
+     * each new variable operand {@linkplain #newVariable(CiKind) allocated} from this pool.
+     */
+    public int size() {
+        return firstVariableNumber + variables.size();
+    }
+
+    /**
+     * Gets the highest operand number for a register operand in this pool. This value will
+     * never change for the lifetime of this pool.
+     */
+    public int maxRegisterNumber() {
+        return firstVariableNumber - 1;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/Range.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.alloc;
+
+
+/**
+ * Represents a range of integers from a start (inclusive) to an end (exclusive.
+ *
+ * @author Thomas Wuerthinger
+ */
+public final class Range {
+
+    public static final Range EndMarker = new Range(Integer.MAX_VALUE, Integer.MAX_VALUE, null);
+
+    /**
+     * The start of the range, inclusive.
+     */
+    public int from;
+
+    /**
+     * The end of the range, exclusive.
+     */
+    public int to;
+
+    /**
+     * A link to allow the range to be put into a singly linked list.
+     */
+    public Range next;
+
+    boolean intersects(Range r) {
+        return intersectsAt(r) != -1;
+    }
+
+
+    /**
+     * Creates a new range.
+     *
+     * @param from the start of the range, inclusive
+     * @param to the end of the range, exclusive
+     * @param next link to the next range in a linked list
+     */
+    Range(int from, int to, Range next) {
+        this.from = from;
+        this.to = to;
+        this.next = next;
+    }
+
+    int intersectsAt(Range r2) {
+        Range r1 = this;
+
+        assert r2 != null : "null ranges not allowed";
+        assert r1 != EndMarker && r2 != EndMarker : "empty ranges not allowed";
+
+        do {
+            if (r1.from < r2.from) {
+                if (r1.to <= r2.from) {
+                    r1 = r1.next;
+                    if (r1 == EndMarker) {
+                        return -1;
+                    }
+                } else {
+                    return r2.from;
+                }
+            } else {
+                if (r2.from < r1.from) {
+                    if (r2.to <= r1.from) {
+                        r2 = r2.next;
+                        if (r2 == EndMarker) {
+                            return -1;
+                        }
+                    } else {
+                        return r1.from;
+                    }
+                } else { // r1.from() == r2.from()
+                    if (r1.from == r1.to) {
+                        r1 = r1.next;
+                        if (r1 == EndMarker) {
+                            return -1;
+                        }
+                    } else {
+                        if (r2.from == r2.to) {
+                            r2 = r2.next;
+                            if (r2 == EndMarker) {
+                                return -1;
+                            }
+                        } else {
+                            return r1.from;
+                        }
+                    }
+                }
+            }
+        } while (true);
+    }
+
+    @Override
+    public String toString() {
+        return "[" + from + ", " + to + "]";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/RegisterVerifier.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.alloc;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.lir.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.sun.cri.ci.*;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+final class RegisterVerifier {
+
+    LinearScan allocator;
+    List<LIRBlock> workList; // all blocks that must be processed
+    ArrayMap<Interval[]> savedStates; // saved information of previous check
+
+    // simplified access to methods of LinearScan
+    GraalCompilation compilation() {
+        return allocator.compilation;
+    }
+
+    Interval intervalAt(CiValue operand) {
+        return allocator.intervalFor(operand);
+    }
+
+    // currently, only registers are processed
+    int stateSize() {
+        return allocator.operands.maxRegisterNumber() + 1;
+    }
+
+    // accessors
+    Interval[] stateForBlock(LIRBlock block) {
+        return savedStates.get(block.blockID());
+    }
+
+    void setStateForBlock(LIRBlock block, Interval[] savedState) {
+        savedStates.put(block.blockID(), savedState);
+    }
+
+    void addToWorkList(LIRBlock block) {
+        if (!workList.contains(block)) {
+            workList.add(block);
+        }
+    }
+
+    RegisterVerifier(LinearScan allocator) {
+        this.allocator = allocator;
+        workList = new ArrayList<LIRBlock>(16);
+        this.savedStates = new ArrayMap<Interval[]>();
+
+    }
+
+    void verify(LIRBlock start) {
+        // setup input registers (method arguments) for first block
+        Interval[] inputState = new Interval[stateSize()];
+        CiCallingConvention args = compilation().frameMap().incomingArguments();
+        for (int n = 0; n < args.locations.length; n++) {
+            CiValue operand = args.locations[n];
+            if (operand.isRegister()) {
+                CiValue reg = operand;
+                Interval interval = intervalAt(reg);
+                inputState[reg.asRegister().number] = interval;
+            }
+        }
+
+        setStateForBlock(start, inputState);
+        addToWorkList(start);
+
+        // main loop for verification
+        do {
+            LIRBlock block = workList.get(0);
+            workList.remove(0);
+
+            processBlock(block);
+        } while (!workList.isEmpty());
+    }
+
+    private void processBlock(LIRBlock block) {
+        if (GraalOptions.TraceLinearScanLevel >= 2) {
+            TTY.println();
+            TTY.println("processBlock B%d", block.blockID());
+        }
+
+        // must copy state because it is modified
+        Interval[] inputState = copy(stateForBlock(block));
+
+        if (GraalOptions.TraceLinearScanLevel >= 4) {
+            TTY.println("Input-State of intervals:");
+            TTY.print("    ");
+            for (int i = 0; i < stateSize(); i++) {
+                if (inputState[i] != null) {
+                    TTY.print(" %4d", inputState[i].operandNumber);
+                } else {
+                    TTY.print("   __");
+                }
+            }
+            TTY.println();
+            TTY.println();
+        }
+
+        // process all operations of the block
+        processOperations(block.lir(), inputState);
+
+        // iterate all successors
+        for (LIRBlock succ : block.blockSuccessors()) {
+            processSuccessor(succ, inputState);
+        }
+    }
+
+    private void processSuccessor(LIRBlock block, Interval[] inputState) {
+        Interval[] savedState = stateForBlock(block);
+
+        if (savedState != null) {
+            // this block was already processed before.
+            // check if new inputState is consistent with savedState
+
+            boolean savedStateCorrect = true;
+            for (int i = 0; i < stateSize(); i++) {
+                if (inputState[i] != savedState[i]) {
+                    // current inputState and previous savedState assume a different
+                    // interval in this register . assume that this register is invalid
+                    if (savedState[i] != null) {
+                        // invalidate old calculation only if it assumed that
+                        // register was valid. when the register was already invalid,
+                        // then the old calculation was correct.
+                        savedStateCorrect = false;
+                        savedState[i] = null;
+
+                        if (GraalOptions.TraceLinearScanLevel >= 4) {
+                            TTY.println("processSuccessor B%d: invalidating slot %d", block.blockID(), i);
+                        }
+                    }
+                }
+            }
+
+            if (savedStateCorrect) {
+                // already processed block with correct inputState
+                if (GraalOptions.TraceLinearScanLevel >= 2) {
+                    TTY.println("processSuccessor B%d: previous visit already correct", block.blockID());
+                }
+            } else {
+                // must re-visit this block
+                if (GraalOptions.TraceLinearScanLevel >= 2) {
+                    TTY.println("processSuccessor B%d: must re-visit because input state changed", block.blockID());
+                }
+                addToWorkList(block);
+            }
+
+        } else {
+            // block was not processed before, so set initial inputState
+            if (GraalOptions.TraceLinearScanLevel >= 2) {
+                TTY.println("processSuccessor B%d: initial visit", block.blockID());
+            }
+
+            setStateForBlock(block, copy(inputState));
+            addToWorkList(block);
+        }
+    }
+
+    Interval[] copy(Interval[] inputState) {
+        return inputState.clone();
+    }
+
+    void statePut(Interval[] inputState, CiValue location, Interval interval) {
+        if (location != null && location.isRegister()) {
+            CiRegister reg = location.asRegister();
+            int regNum = reg.number;
+            if (interval != null) {
+                if (GraalOptions.TraceLinearScanLevel >= 4) {
+                    TTY.println("        %s = %s", reg, interval.operand);
+                }
+            } else if (inputState[regNum] != null) {
+                if (GraalOptions.TraceLinearScanLevel >= 4) {
+                    TTY.println("        %s = null", reg);
+                }
+            }
+
+            inputState[regNum] = interval;
+        }
+    }
+
+    boolean checkState(Interval[] inputState, CiValue reg, Interval interval) {
+        if (reg != null && reg.isRegister()) {
+            if (inputState[reg.asRegister().number] != interval) {
+                throw new CiBailout("!! Error in register allocation: register " + reg + " does not contain interval " + interval.operand + " but interval " + inputState[reg.asRegister().number]);
+            }
+        }
+        return true;
+    }
+
+    void processOperations(LIRList ops, Interval[] inputState) {
+        // visit all instructions of the block
+        for (int i = 0; i < ops.length(); i++) {
+            LIRInstruction op = ops.at(i);
+
+            if (GraalOptions.TraceLinearScanLevel >= 4) {
+                TTY.println(op.toStringWithIdPrefix());
+            }
+
+            // check if input operands are correct
+            int n = op.operandCount(LIRInstruction.OperandMode.Input);
+            for (int j = 0; j < n; j++) {
+                CiValue operand = op.operandAt(LIRInstruction.OperandMode.Input, j);
+                if (allocator.isProcessed(operand)) {
+                    Interval interval = intervalAt(operand);
+                    if (op.id() != -1) {
+                        interval = interval.getSplitChildAtOpId(op.id(), LIRInstruction.OperandMode.Input, allocator);
+                    }
+
+                    assert checkState(inputState, interval.location(), interval.splitParent());
+                }
+            }
+
+            // invalidate all caller save registers at calls
+            if (op.hasCall) {
+                for (CiRegister r : allocator.compilation.registerConfig.getCallerSaveRegisters()) {
+                    statePut(inputState, r.asValue(), null);
+                }
+            }
+
+            // set temp operands (some operations use temp operands also as output operands, so can't set them null)
+            n = op.operandCount(LIRInstruction.OperandMode.Temp);
+            for (int j = 0; j < n; j++) {
+                CiValue operand = op.operandAt(LIRInstruction.OperandMode.Temp, j);
+                if (allocator.isProcessed(operand)) {
+                    Interval interval = intervalAt(operand);
+                    assert interval != null : "Could not find interval for operand " + operand;
+                    if (op.id() != -1) {
+                        interval = interval.getSplitChildAtOpId(op.id(), LIRInstruction.OperandMode.Temp, allocator);
+                    }
+
+                    statePut(inputState, interval.location(), interval.splitParent());
+                }
+            }
+
+            // set output operands
+            n = op.operandCount(LIRInstruction.OperandMode.Output);
+            for (int j = 0; j < n; j++) {
+                CiValue operand = op.operandAt(LIRInstruction.OperandMode.Output, j);
+                if (allocator.isProcessed(operand)) {
+                    Interval interval = intervalAt(operand);
+                    if (op.id() != -1) {
+                        interval = interval.getSplitChildAtOpId(op.id(), LIRInstruction.OperandMode.Output, allocator);
+                    }
+
+                    statePut(inputState, interval.location(), interval.splitParent());
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/asm/ExceptionInfo.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.asm;
+
+import com.oracle.max.graal.compiler.lir.*;
+
+public class ExceptionInfo {
+
+    public final int codeOffset;
+    public final LIRBlock exceptionEdge;
+    public final int bci;
+
+    public ExceptionInfo(int pcOffset, LIRBlock exceptionEdge, int bci) {
+        this.codeOffset = pcOffset;
+        this.exceptionEdge = exceptionEdge;
+        this.bci = bci;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/asm/TargetMethodAssembler.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.asm;
+
+import java.util.*;
+
+import com.oracle.max.asm.*;
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.lir.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+public class TargetMethodAssembler {
+    public final AbstractAssembler asm;
+    public final CiTargetMethod targetMethod;
+    public List<ExceptionInfo> exceptionInfoList;
+    protected int lastSafepointPos;
+
+    public TargetMethodAssembler(AbstractAssembler asm) {
+        this.asm = asm;
+        this.targetMethod = new CiTargetMethod();
+    }
+
+    public void setFrameSize(int frameSize) {
+        targetMethod.setFrameSize(frameSize);
+    }
+
+    public CiTargetMethod.Mark recordMark(Object id, CiTargetMethod.Mark[] references) {
+        return targetMethod.recordMark(asm.codeBuffer.position(), id, references);
+    }
+
+    public void blockComment(String s) {
+        targetMethod.addAnnotation(new CiTargetMethod.CodeComment(asm.codeBuffer.position(), s));
+    }
+
+    public CiTargetMethod finishTargetMethod(Object name, RiRuntime runtime, int registerRestoreEpilogueOffset, boolean isStub) {
+        // Install code, data and frame size
+        targetMethod.setTargetCode(asm.codeBuffer.close(false), asm.codeBuffer.position());
+        targetMethod.setRegisterRestoreEpilogueOffset(registerRestoreEpilogueOffset);
+
+        // Record exception handlers if they exist
+        if (exceptionInfoList != null) {
+            for (ExceptionInfo ei : exceptionInfoList) {
+                int codeOffset = ei.codeOffset;
+                targetMethod.recordExceptionHandler(codeOffset, -1, 0, ei.exceptionEdge.blockEntryPco, -1, null);
+            }
+        }
+
+        if (GraalOptions.Meter) {
+            GraalMetrics.TargetMethods++;
+            GraalMetrics.CodeBytesEmitted += targetMethod.targetCodeSize();
+            GraalMetrics.SafepointsEmitted += targetMethod.safepoints.size();
+            GraalMetrics.DirectCallSitesEmitted += targetMethod.directCalls.size();
+            GraalMetrics.IndirectCallSitesEmitted += targetMethod.indirectCalls.size();
+            GraalMetrics.DataPatches += targetMethod.dataReferences.size();
+            GraalMetrics.ExceptionHandlersEmitted += targetMethod.exceptionHandlers.size();
+        }
+
+        if (GraalOptions.PrintAssembly && !TTY.isSuppressed() && !isStub) {
+            Util.printSection("Target Method", Util.SECTION_CHARACTER);
+            TTY.println("Name: " + name);
+            TTY.println("Frame size: " + targetMethod.frameSize());
+            TTY.println("Register size: " + asm.target.arch.registerReferenceMapBitCount);
+
+            if (GraalOptions.PrintCodeBytes) {
+                Util.printSection("Code", Util.SUB_SECTION_CHARACTER);
+                TTY.println("Code: %d bytes", targetMethod.targetCodeSize());
+                Util.printBytes(0L, targetMethod.targetCode(), 0, targetMethod.targetCodeSize(), GraalOptions.PrintAssemblyBytesPerLine);
+            }
+
+            Util.printSection("Disassembly", Util.SUB_SECTION_CHARACTER);
+            String disassembly = runtime.disassemble(targetMethod);
+            TTY.println(disassembly);
+            boolean noDis = disassembly == null || disassembly.length() == 0;
+
+            Util.printSection("Safepoints", Util.SUB_SECTION_CHARACTER);
+            for (CiTargetMethod.Safepoint x : targetMethod.safepoints) {
+                TTY.println(x.toString());
+                if (noDis && x.debugInfo != null) {
+                    TTY.println(CiUtil.indent(x.debugInfo.toString(), "  "));
+                }
+            }
+
+            Util.printSection("Direct Call Sites", Util.SUB_SECTION_CHARACTER);
+            for (CiTargetMethod.Call x : targetMethod.directCalls) {
+                TTY.println(x.toString());
+                if (noDis && x.debugInfo != null) {
+                    TTY.println(CiUtil.indent(x.debugInfo.toString(), "  "));
+                }
+            }
+
+            Util.printSection("Indirect Call Sites", Util.SUB_SECTION_CHARACTER);
+            for (CiTargetMethod.Call x : targetMethod.indirectCalls) {
+                TTY.println(x.toString());
+                if (noDis && x.debugInfo != null) {
+                    TTY.println(CiUtil.indent(x.debugInfo.toString(), "  "));
+                }
+            }
+
+            Util.printSection("Data Patches", Util.SUB_SECTION_CHARACTER);
+            for (CiTargetMethod.DataPatch x : targetMethod.dataReferences) {
+                TTY.println(x.toString());
+            }
+
+            Util.printSection("Marks", Util.SUB_SECTION_CHARACTER);
+            for (CiTargetMethod.Mark x : targetMethod.marks) {
+                TTY.println(x.toString());
+            }
+
+            Util.printSection("Exception Handlers", Util.SUB_SECTION_CHARACTER);
+            for (CiTargetMethod.ExceptionHandler x : targetMethod.exceptionHandlers) {
+                TTY.println(x.toString());
+            }
+        }
+
+        return targetMethod;
+    }
+
+    public void recordExceptionHandlers(int pcOffset, LIRDebugInfo info) {
+        if (info != null) {
+            if (info.exceptionEdge() != null) {
+                if (exceptionInfoList == null) {
+                    exceptionInfoList = new ArrayList<ExceptionInfo>(4);
+                }
+                exceptionInfoList.add(new ExceptionInfo(pcOffset, info.exceptionEdge(), info.state.bci));
+            }
+        }
+    }
+
+    public void recordImplicitException(int pcOffset, LIRDebugInfo info) {
+        // record an implicit exception point
+        if (info != null) {
+            assert lastSafepointPos < pcOffset;
+            lastSafepointPos = pcOffset;
+            targetMethod.recordSafepoint(pcOffset, info.debugInfo());
+            assert info.exceptionEdge() == null;
+        }
+    }
+
+    public void recordDirectCall(int posBefore, int posAfter, Object target, LIRDebugInfo info) {
+        CiDebugInfo debugInfo = info != null ? info.debugInfo() : null;
+        assert lastSafepointPos < posAfter;
+        lastSafepointPos = posAfter;
+        targetMethod.recordCall(posBefore, target, debugInfo, true);
+    }
+
+    public void recordIndirectCall(int posBefore, int posAfter, Object target, LIRDebugInfo info) {
+        CiDebugInfo debugInfo = info != null ? info.debugInfo() : null;
+        assert lastSafepointPos < posAfter;
+        lastSafepointPos = posAfter;
+        targetMethod.recordCall(posBefore, target, debugInfo, false);
+    }
+
+    public void recordSafepoint(int pos, LIRDebugInfo info) {
+        // safepoints always need debug info
+        CiDebugInfo debugInfo = info.debugInfo();
+        assert lastSafepointPos < pos;
+        lastSafepointPos = pos;
+        targetMethod.recordSafepoint(pos, debugInfo);
+    }
+
+    public CiAddress recordDataReferenceInCode(CiConstant data) {
+        assert data != null;
+
+        int pos = asm.codeBuffer.position();
+
+        if (GraalOptions.TraceRelocation) {
+            TTY.print("Data reference in code: pos = %d, data = %s", pos, data.toString());
+        }
+
+        targetMethod.recordDataReference(pos, data);
+        return CiAddress.Placeholder;
+    }
+
+    public int lastSafepointPos() {
+        return lastSafepointPos;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/BlockPrinter.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.debug;
+
+import com.oracle.max.graal.compiler.graph.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.schedule.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.compiler.value.*;
+import com.oracle.max.graal.graph.*;
+
+/**
+ * Prints a listing for a {@linkplain Merge block}.
+ */
+public class BlockPrinter implements BlockClosure {
+
+    private final InstructionPrinter ip;
+    private final boolean cfgOnly;
+
+    public BlockPrinter(IR ir, InstructionPrinter ip, boolean cfgOnly) {
+        this.ip = ip;
+        this.cfgOnly = cfgOnly;
+    }
+
+    public void apply(Block block) {
+        if (cfgOnly) {
+            if (block.getInstructions().size() > 0) {
+                ip.printInstruction((FixedNodeWithNext) block.getInstructions().get(0));
+            } else {
+                ip.out().println("Empty block");
+            }
+            ip.out().println();
+        } else {
+            printBlock(block);
+        }
+    }
+
+    public void printBlock(Block block) {
+        LogStream out = ip.out();
+        out.println();
+
+        ip.printInstructionListingHeader();
+
+        for (Node i : block.getInstructions()) {
+            if (i instanceof FixedNodeWithNext) {
+                ip.printInstructionListing((FixedNodeWithNext) i);
+            }
+        }
+        out.println();
+
+    }
+
+    private static void printFrameState(FrameState newFrameState, LogStream out) {
+        int startPosition = out.position();
+        if (newFrameState.stackSize() == 0) {
+          out.print("empty stack");
+        } else {
+          out.print("stack [");
+          int i = 0;
+          while (i < newFrameState.stackSize()) {
+            if (i > 0) {
+                out.print(", ");
+            }
+            Value value = newFrameState.stackAt(i);
+            out.print(i + ":" + Util.valueString(value));
+            if (value == null) {
+                i++;
+            } else {
+                i += value.kind.sizeInSlots();
+                if (value instanceof Phi) {
+                    Phi phi = (Phi) value;
+                    if (phi.operand() != null) {
+                        out.print(" ");
+                        out.print(phi.operand().toString());
+                    }
+                }
+            }
+          }
+          out.print(']');
+        }
+        if (newFrameState.locksSize() != 0) {
+            // print out the lines on the line below this
+            // one at the same indentation level.
+            out.println();
+            out.fillTo(startPosition, ' ');
+            out.print("locks [");
+            for (int i = 0; i < newFrameState.locksSize(); i++) {
+                Value value = newFrameState.lockAt(i);
+                if (i > 0) {
+                    out.print(", ");
+                }
+                out.print(i + ":");
+                if (value == null) {
+                    // synchronized methods push null on the lock stack
+                    out.print("this");
+                } else {
+                    out.print(Util.valueString(value));
+                }
+            }
+            out.print("]");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/CFGPrinter.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,639 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.debug;
+
+import java.io.*;
+import java.util.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.alloc.*;
+import com.oracle.max.graal.compiler.alloc.Interval.*;
+import com.oracle.max.graal.compiler.graph.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.lir.*;
+import com.oracle.max.graal.compiler.lir.LIRInstruction.*;
+import com.oracle.max.graal.compiler.schedule.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.compiler.value.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ci.CiAddress.*;
+import com.sun.cri.ri.*;
+
+/**
+ * Utility for printing the control flow graph of a method being compiled by Graal at various compilation phases.
+ * The output format matches that produced by HotSpot so that it can then be fed to the
+ * <a href="https://c1visualizer.dev.java.net/">C1 Visualizer</a>.
+ */
+public class CFGPrinter {
+    private static final String COLUMN_END = " <|@";
+    private static final String HOVER_START = "<@";
+    private static final String HOVER_SEP = "|@";
+    private static final String HOVER_END = ">@";
+
+    private static OutputStream cfgFileStream;
+
+    /**
+     * Gets the output stream  on the file "output.cfg" in the current working directory.
+     * This stream is first opened if necessary.
+     *
+     * @return the output stream to "output.cfg" or {@code null} if there was an error opening this file for writing
+     */
+    public static synchronized OutputStream cfgFileStream() {
+        if (cfgFileStream == null) {
+            File cfgFile = new File("output.cfg");
+            try {
+                cfgFileStream = new FileOutputStream(cfgFile);
+            } catch (FileNotFoundException e) {
+                TTY.println("WARNING: Could not open " + cfgFile.getAbsolutePath());
+            }
+        }
+        return cfgFileStream;
+    }
+
+    private final LogStream out;
+    private final CiTarget target;
+
+    /**
+     * Creates a control flow graph printer.
+     *
+     * @param os where the output generated via this printer shown be written
+     * @param target the target architecture description
+     */
+    public CFGPrinter(OutputStream os, CiTarget target) {
+        out = new LogStream(os);
+        this.target = target;
+    }
+
+    /**
+     * Flushes all buffered output to the stream passed to {@link #CFGPrinter(OutputStream, CiTarget)}.
+     */
+    public void flush() {
+        out.flush();
+    }
+
+    private void begin(String string) {
+        out.println("begin_" + string);
+        out.adjustIndentation(2);
+    }
+
+    private void end(String string) {
+        out.adjustIndentation(-2);
+        out.println("end_" + string);
+    }
+
+    /**
+     * Prints a compilation timestamp for a given method.
+     *
+     * @param method the method for which a timestamp will be printed
+     */
+    public void printCompilation(RiMethod method) {
+        begin("compilation");
+        out.print("name \" ").print(CiUtil.format("%H::%n", method, true)).println('"');
+        out.print("method \"").print(CiUtil.format("%f %r %H.%n(%p)", method, true)).println('"');
+        out.print("date ").println(System.currentTimeMillis());
+        end("compilation");
+    }
+
+    /**
+     * Print the details of a given control flow graph block.
+     *
+     * @param block the block to print
+     * @param successors the successor blocks of {@code block}
+     * @param handlers the exception handler blocks of {@code block}
+     * @param printHIR if {@code true} the HIR for each instruction in the block will be printed
+     * @param printLIR if {@code true} the LIR for each instruction in the block will be printed
+     */
+    void printBlock(Block block, List<Block> successors, Block handler, boolean printHIR, boolean printLIR) {
+        begin("block");
+
+        out.print("name \"B").print(block.blockID()).println('"');
+        out.print("from_bci -1");
+        out.print("to_bci -1");
+
+        out.print("predecessors ");
+        for (Block pred : block.getPredecessors()) {
+            out.print("\"B").print(pred.blockID()).print("\" ");
+        }
+        out.println();
+
+        out.print("successors ");
+        for (Block succ : successors) {
+            out.print("\"B").print(succ.blockID()).print("\" ");
+        }
+        out.println();
+
+        out.print("xhandlers");
+        if (handler != null) {
+            out.print("\"B").print(handler.blockID()).print("\" ");
+        }
+        out.println();
+
+        out.print("flags ");
+        out.println();
+
+        out.print("loop_index ").println(-1);
+        out.print("loop_depth ").println(-1);
+
+        if (printHIR) {
+            printHIR(block);
+        }
+
+        // TODO(tw): Add possibility to print LIR.
+        //if (printLIR) {
+        //    printLIR(block.lirBlock());
+        //}
+
+        end("block");
+    }
+
+    /**
+     * Prints the JVM frame state upon entry to a given block.
+     *
+     * @param block the block for which the frame state is to be printed
+     */
+    /*private void printState(Block block) {
+        begin("states");
+
+        FrameState state = block.stateBefore();
+        if (state == null) {
+            return;
+        }
+        int stackSize = state.stackSize();
+        if (stackSize > 0) {
+            begin("stack");
+            out.print("size ").println(stackSize);
+            out.print("method \"").print(CiUtil.toLocation(GraalCompilation.compilation().method, state.bci)).println('"');
+
+            int i = 0;
+            while (i < stackSize) {
+                Value value = state.stackAt(i);
+                out.disableIndentation();
+                out.print(block.stateString(i, value));
+                printOperand(value);
+                out.println();
+                out.enableIndentation();
+                if (value == null) {
+                    i++;
+                } else {
+                    i += value.kind.sizeInSlots();
+                }
+            }
+            end("stack");
+        }
+
+        if (state.locksSize() > 0) {
+            begin("locks");
+            out.print("size ").println(state.locksSize());
+            out.print("method \"").print(CiUtil.toLocation(GraalCompilation.compilation().method, state.bci)).println('"');
+
+            for (int i = 0; i < state.locksSize(); ++i) {
+                Value value = state.lockAt(i);
+                out.disableIndentation();
+                out.print(block.stateString(i, value));
+                printOperand(value);
+                out.println();
+                out.enableIndentation();
+            }
+            end("locks");
+        }
+
+        begin("locals");
+        out.print("size ").println(state.localsSize());
+        out.print("method \"").print(CiUtil.toLocation(GraalCompilation.compilation().method, state.bci)).println('"');
+        int i = 0;
+        while (i < state.localsSize()) {
+            Value value = state.localAt(i);
+            if (value != null) {
+                out.disableIndentation();
+                out.print(block.stateString(i, value));
+                printOperand(value);
+                out.println();
+                out.enableIndentation();
+                // also ignore illegal HiWords
+                i += value.isIllegal() ? 1 : value.kind.sizeInSlots();
+            } else {
+                i++;
+            }
+        }
+        end("locals");
+        end("states");
+    }*/
+
+    /**
+     * Formats a given {@linkplain FrameState JVM frame state} as a multi line string.
+     */
+    private String stateToString(FrameState state, CFGOperandFormatter operandFmt) {
+        if (state == null) {
+            return null;
+        }
+
+        StringBuilder buf = new StringBuilder();
+        buf.append(CiUtil.toLocation(GraalCompilation.compilation().method, state.bci));
+        buf.append('\n');
+        if (state.stackSize() > 0) {
+            int i = 0;
+            buf.append("stack: ");
+            while (i < state.stackSize()) {
+                if (i == 0) {
+                    buf.append(' ');
+                }
+                Value value = state.stackAt(i);
+                buf.append(stateValueToString(value, operandFmt)).append(' ');
+                i++;
+            }
+            buf.append("\n");
+        }
+
+        if (state.locksSize() > 0) {
+            buf.append("locks: ");
+            for (int i = 0; i < state.locksSize(); ++i) {
+                if (i == 0) {
+                    buf.append(' ');
+                }
+                Value value = state.lockAt(i);
+                buf.append(stateValueToString(value, operandFmt)).append(' ');
+            }
+            buf.append("\n");
+        }
+
+        buf.append("locals: ");
+        int i = 0;
+        while (i < state.localsSize()) {
+            if (i == 0) {
+                buf.append(' ');
+            }
+            Value value = state.localAt(i);
+            buf.append(stateValueToString(value, operandFmt)).append(' ');
+            i++;
+        }
+        buf.append("\n");
+        return buf.toString();
+    }
+
+    private String stateValueToString(Value value, OperandFormatter operandFmt) {
+        if (operandFmt == null) {
+            return Util.valueString(value);
+        }
+        if (value == null) {
+            return "-";
+        }
+        return operandFmt.format(value.operand());
+    }
+
+    private String stateValueToString(CiValue value, OperandFormatter operandFmt) {
+        if (value == null) {
+            return "-";
+        }
+        return operandFmt.format(value);
+    }
+
+    /**
+     * Formats a given {@linkplain FrameState JVM frame state} as a multi line string.
+     */
+    private String debugInfoToString(CiDebugInfo info, CFGOperandFormatter operandFmt) {
+        if (info == null) {
+            return null;
+        }
+        StringBuilder sb = new StringBuilder();
+
+
+        if (info.hasRegisterRefMap()) {
+            sb.append("reg-ref-map:");
+            GraalCompilation compilation = GraalCompilation.compilation();
+            CiArchitecture arch = compilation == null ? null : compilation.target.arch;
+            for (int reg = info.registerRefMap.nextSetBit(0); reg >= 0; reg = info.registerRefMap.nextSetBit(reg + 1)) {
+                sb.append(' ').append(arch == null ? "reg" + reg : arch.registers[reg]);
+            }
+            sb.append("\n");
+        }
+        if (info.hasStackRefMap()) {
+            sb.append("frame-ref-map:");
+            BitMap bm = info.frameRefMap;
+            for (int i = bm.nextSetBit(0); i >= 0; i = bm.nextSetBit(i + 1)) {
+                sb.append(' ').append(CiStackSlot.get(CiKind.Object, i));
+            }
+            sb.append("\n");
+        }
+        if (info.codePos != null) {
+            sb.append(stateToString(info.codePos, operandFmt));
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Formats a given {@linkplain FrameState JVM frame state} as a multi line string.
+     */
+    private String stateToString(CiCodePos codePos, CFGOperandFormatter operandFmt) {
+        if (codePos == null) {
+            return null;
+        }
+
+        StringBuilder buf = new StringBuilder();
+
+        do {
+            buf.append(CiUtil.toLocation(codePos.method, codePos.bci));
+            buf.append('\n');
+            if (codePos instanceof CiFrame) {
+                CiFrame frame = (CiFrame) codePos;
+                if (frame.numStack > 0) {
+                    int i = 0;
+                    buf.append("stack: ");
+                    while (i < frame.numStack) {
+                        if (i == 0) {
+                            buf.append(' ');
+                        }
+                        CiValue value = frame.getStackValue(i);
+                        buf.append(stateValueToString(value, operandFmt)).append(' ');
+                        i++;
+                    }
+                    buf.append("\n");
+                }
+
+                if (frame.numLocks > 0) {
+                    buf.append("locks: ");
+                    for (int i = 0; i < frame.numLocks; ++i) {
+                        if (i == 0) {
+                            buf.append(' ');
+                        }
+                        CiValue value = frame.getLockValue(i);
+                        buf.append(stateValueToString(value, operandFmt)).append(' ');
+                    }
+                    buf.append("\n");
+                }
+
+                buf.append("locals: ");
+                int i = 0;
+                while (i < frame.numLocals) {
+                    if (i == 0) {
+                        buf.append(' ');
+                    }
+                    CiValue value = frame.getLocalValue(i);
+                    buf.append(stateValueToString(value, operandFmt)).append(' ');
+                    i++;
+                }
+                buf.append("\n");
+            }
+            codePos = codePos.caller;
+        } while (codePos != null);
+        return buf.toString();
+    }
+
+    /**
+     * Prints the HIR for each instruction in a given block.
+     *
+     * @param block
+     */
+    private void printHIR(Block block) {
+        begin("IR");
+        out.println("HIR");
+        out.disableIndentation();
+        for (Node i : block.getInstructions()) {
+            if (i instanceof FixedNodeWithNext) {
+                printInstructionHIR((FixedNodeWithNext) i);
+            }
+        }
+        out.enableIndentation();
+        end("IR");
+    }
+
+    /**
+     * Formats LIR operands as expected by the C1 Visualizer.
+     */
+    public static class CFGOperandFormatter extends OperandFormatter {
+        /**
+         * The textual delimiters used for an operand depend on the context in which it is being
+         * printed. When printed as part of a frame state or as the result operand in a HIR node listing,
+         * it is enclosed in double-quotes (i.e. {@code "}'s).
+         */
+        public final boolean asStateOrHIROperandResult;
+
+        public CFGOperandFormatter(boolean asStateOrHIROperandResult) {
+            this.asStateOrHIROperandResult = asStateOrHIROperandResult;
+        }
+
+        @Override
+        public String format(CiValue operand) {
+            if (operand.isLegal()) {
+                String op;
+                if (operand.isVariableOrRegister() || operand.isStackSlot()) {
+                    op = operand.name();
+                } else if (operand.isConstant()) {
+                    CiConstant constant = (CiConstant) operand;
+                    op = operand.kind.javaName + ":" + operand.kind.format(constant.boxedValue());
+                } else if (operand.isAddress()) {
+                    CiAddress address = (CiAddress) operand;
+                    op = "Base:" + format(address.base);
+                    if (!address.index.isIllegal()) {
+                        op += " Index:" + format(address.index);
+                    }
+                    if (address.scale != Scale.Times1) {
+                        op += " * " + address.scale.value;
+                    }
+                    op += " Disp:" + address.displacement;
+                } else {
+                    assert operand.isIllegal();
+                    op = "-";
+                }
+                if (operand.kind != CiKind.Illegal) {
+                    op += "|" + operand.kind.typeChar;
+                }
+                if (asStateOrHIROperandResult) {
+                    op = " \"" + op.replace('"', '\'') + "\" ";
+                }
+                return op;
+            }
+            return "";
+        }
+    }
+
+    /**
+     * Prints the LIR for each instruction in a given block.
+     *
+     * @param block the block to print
+     */
+    private void printLIR(LIRBlock block) {
+        LIRList lir = block.lir();
+        if (lir != null) {
+            begin("IR");
+            out.println("LIR");
+            for (int i = 0; i < lir.length(); i++) {
+                LIRInstruction inst = lir.at(i);
+                out.printf("nr %4d ", inst.id()).print(COLUMN_END);
+
+                if (inst.info != null) {
+                    int level = out.indentationLevel();
+                    out.adjustIndentation(-level);
+                    String state;
+                    if (inst.info.debugInfo != null) {
+                        // Use register-allocator output if available
+                        state = debugInfoToString(inst.info.debugInfo, new CFGOperandFormatter(false));
+                    } else {
+                        state = stateToString(inst.info.state, new CFGOperandFormatter(false));
+                    }
+                    if (state != null) {
+                        out.print(" st ").print(HOVER_START).print("st").print(HOVER_SEP).print(state).print(HOVER_END).print(COLUMN_END);
+                    }
+                    out.adjustIndentation(level);
+                }
+
+                out.print(" instruction ").print(inst.toString(new CFGOperandFormatter(false))).print(COLUMN_END);
+                out.println(COLUMN_END);
+            }
+            end("IR");
+        }
+    }
+
+    private void printOperand(Value i) {
+        if (i != null && i.operand().isLegal()) {
+            out.print(new CFGOperandFormatter(true).format(i.operand()));
+        }
+    }
+
+    /**
+     * Prints the HIR for a given instruction.
+     *
+     * @param i the instruction for which HIR will be printed
+     */
+    private void printInstructionHIR(FixedNodeWithNext i) {
+        out.print("bci ").print(-1).println(COLUMN_END);
+        if (i.operand().isLegal()) {
+            out.print("result ").print(new CFGOperandFormatter(false).format(i.operand())).println(COLUMN_END);
+        }
+        out.print("tid ").print(i).println(COLUMN_END);
+
+        if (i instanceof StateSplit) {
+            StateSplit stateSplit = (StateSplit) i;
+            String state = stateToString(stateSplit.stateAfter(), null);
+            if (state != null) {
+                out.print("st ").print(HOVER_START).print("st").print(HOVER_SEP).print(state).print(HOVER_END).println(COLUMN_END);
+            }
+        }
+
+        out.print("instruction ");
+        i.print(out);
+        out.print(COLUMN_END).print(' ').println(COLUMN_END);
+    }
+
+    /**
+     * Prints the control flow graph denoted by a given block map.
+     *
+     * @param blockMap a data structure describing the blocks in a method and how they are connected
+     * @param codeSize the bytecode size of the method from which {@code blockMap} was produced
+     * @param label a label describing the compilation phase that produced the control flow graph
+     * @param printHIR if {@code true} the HIR for each instruction in the block will be printed
+     * @param printLIR if {@code true} the LIR for each instruction in the block will be printed
+     */
+    public void printCFG(RiMethod method, BlockMap blockMap, int codeSize, String label, boolean printHIR, boolean printLIR) {
+        begin("cfg");
+        out.print("name \"").print(label).println('"');
+        for (BlockMap.Block block : blockMap.blocks) {
+            begin("block");
+            blockMap.printBlock(block, out);
+            end("block");
+        }
+        end("cfg");
+    }
+
+    /**
+     * Prints the control flow graph rooted at a given block.
+     *
+     * @param startBlock the entry block of the control flow graph to be printed
+     * @param label a label describing the compilation phase that produced the control flow graph
+     * @param printHIR if {@code true} the HIR for each instruction in the block will be printed
+     * @param printLIR if {@code true} the LIR for each instruction in the block will be printed
+     */
+    public void printCFG(Block startBlock, String label, final boolean printHIR, final boolean printLIR) {
+        begin("cfg");
+        out.print("name \"").print(label).println('"');
+        startBlock.iteratePreOrder(new BlockClosure() {
+            public void apply(Block block) {
+                List<Block> successors = block.getSuccessors();
+                printBlock(block, successors, null, printHIR, printLIR);
+            }
+        });
+        end("cfg");
+    }
+
+    public void printIntervals(LinearScan allocator, Interval[] intervals, String name) {
+        begin("intervals");
+        out.println(String.format("name \"%s\"", name));
+
+        for (Interval interval : intervals) {
+            if (interval != null) {
+                printInterval(allocator, interval);
+            }
+        }
+
+        end("intervals");
+    }
+
+    private void printInterval(LinearScan allocator, Interval interval) {
+        out.printf("%d %s ", interval.operandNumber, (interval.operand.isRegister() ? "fixed" : interval.kind().name()));
+        if (interval.operand.isRegister()) {
+            out.printf("\"[%s|%c]\"", interval.operand.name(), interval.operand.kind.typeChar);
+        } else {
+            if (interval.location() != null) {
+                out.printf("\"[%s|%c]\"", interval.location().name(), interval.location().kind.typeChar);
+            }
+        }
+
+        Interval hint = interval.locationHint(false, allocator);
+        out.printf("%d %d ", interval.splitParent().operandNumber, hint != null ? hint.operandNumber : -1);
+
+        // print ranges
+        Range cur = interval.first();
+        while (cur != Range.EndMarker) {
+            out.printf("[%d, %d[", cur.from, cur.to);
+            cur = cur.next;
+            assert cur != null : "range list not closed with range sentinel";
+        }
+
+        // print use positions
+        int prev = 0;
+        UsePosList usePosList = interval.usePosList();
+        for (int i = usePosList.size() - 1; i >= 0; --i) {
+            assert prev < usePosList.usePos(i) : "use positions not sorted";
+            out.printf("%d %s ", usePosList.usePos(i), usePosList.registerPriority(i));
+            prev = usePosList.usePos(i);
+        }
+
+        out.printf(" \"%s\"", interval.spillState());
+        out.println();
+    }
+
+    public void printMachineCode(String code, String label) {
+        if (code.length() == 0) {
+            return;
+        }
+        if (label != null) {
+            begin("cfg");
+            out.print("name \"").print(label).println('"');
+            end("cfg");
+        }
+        begin("nmethod");
+        out.print(code);
+        out.println(" <|@");
+        end("nmethod");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/CFGPrinterObserver.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,120 @@
+/*
+ * 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.max.graal.compiler.debug;
+
+import java.io.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.observer.*;
+import com.sun.cri.ri.*;
+
+/**
+ * Observes compilation events and uses {@link CFGPrinter} to produce a control flow graph for the <a
+ * href="https://c1visualizer.dev.java.net/">C1 Visualizer</a>.
+ *
+ * @author Peter Hofer
+ */
+public class CFGPrinterObserver implements CompilationObserver {
+
+    private GraalCompilation currentCompilation;
+    private CFGPrinter cfgPrinter;
+    private ByteArrayOutputStream buffer = null;
+    private final OutputStream stream;
+
+    public CFGPrinterObserver() {
+        this(CFGPrinter.cfgFileStream());
+    }
+
+    public CFGPrinterObserver(OutputStream stream) {
+        this.stream = stream;
+    }
+
+    @Override
+    public void compilationStarted(CompilationEvent event) {
+        // Supports only one compilation at the same time
+        assert currentCompilation == null;
+
+        currentCompilation = event.getCompilation();
+        if (buffer == null) {
+            buffer = new ByteArrayOutputStream();
+        }
+        cfgPrinter = new CFGPrinter(buffer, currentCompilation.target);
+        cfgPrinter.printCompilation(currentCompilation.method);
+    }
+
+    @Override
+    public void compilationEvent(CompilationEvent event) {
+        assert currentCompilation == event.getCompilation();
+
+        String label = event.getLabel();
+
+        if (event.getAllocator() != null && event.getIntervals() != null) {
+            cfgPrinter.printIntervals(event.getAllocator(), event.getIntervals(), label);
+        }
+
+        boolean cfgprinted = false;
+
+        if (event.getBlockMap() != null && event.getCodeSize() >= 0) {
+            cfgPrinter.printCFG(event.getMethod(), event.getBlockMap(), event.getCodeSize(), label, event.isHIRValid(), event.isLIRValid());
+            cfgprinted = true;
+        }
+
+        // TODO fix that when schedule is here (startBlock : Instruction->Block)
+        /*if (event.getStartBlock() != null) {
+            cfgPrinter.printCFG((BlockBegin) event.getStartBlock(), label, event.isHIRValid(), event.isLIRValid());
+            cfgprinted = true;
+        }*/
+
+        if (event.getTargetMethod() != null) {
+            if (cfgprinted) {
+                // Avoid duplicate "cfg" section
+                label = null;
+            }
+
+            RiRuntime runtime = event.getCompilation().runtime;
+            cfgPrinter.printMachineCode(runtime.disassemble(event.getTargetMethod()), label);
+        }
+    }
+
+    @Override
+    public void compilationFinished(CompilationEvent event) {
+        assert currentCompilation == event.getCompilation();
+
+        cfgPrinter.flush();
+
+        if (stream != null) {
+            synchronized (stream) {
+                try {
+                    stream.write(buffer.toByteArray());
+                    stream.flush();
+                } catch (IOException e) {
+                    TTY.println("WARNING: Error writing CFGPrinter output for %s: %s", event.getMethod(), e);
+                }
+            }
+        }
+
+        buffer.reset();
+        cfgPrinter = null;
+        currentCompilation = null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/GraphvizPrinterObserver.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,110 @@
+/*
+ * 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.max.graal.compiler.debug;
+
+import java.io.*;
+import java.util.regex.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.observer.*;
+import com.oracle.max.graal.compiler.value.*;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.graphviz.*;
+
+/**
+ * Observes compilation events and uses {@link GraphvizPrinter} to produce a control flow graph in the DOT language
+ * which can be visualized with Graphviz.
+ *
+ * @author Peter Hofer
+ */
+public class GraphvizPrinterObserver implements CompilationObserver {
+
+    private static final Pattern INVALID_CHAR = Pattern.compile("[^A-Za-z0-9_.-]");
+
+    private final boolean pdf;
+    private int n;
+
+    public GraphvizPrinterObserver(boolean pdf) {
+        this.pdf = pdf;
+    }
+
+    public void compilationStarted(CompilationEvent event) {
+        n = 0;
+    }
+
+    public void compilationFinished(CompilationEvent event) {
+    }
+
+    public void compilationEvent(CompilationEvent event) {
+        if (event.getGraph() != null && !TTY.isSuppressed()) {
+            Graph graph = event.getGraph();
+
+            String name = event.getMethod().holder().name();
+            name = name.substring(1, name.length() - 1).replace('/', '.');
+            name = name + "." + event.getMethod().name();
+
+            String filename = name + "_" + (n++) + "_" + event.getLabel();
+            filename = INVALID_CHAR.matcher(filename).replaceAll("_");
+
+            OutputStream out = null;
+            try {
+                if (pdf) {
+                    ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+                    printGraph(graph, name, buffer);
+
+                    out = new FileOutputStream(filename + ".pdf");
+                    GraphvizRunner.process(GraphvizRunner.DOT_LAYOUT, new ByteArrayInputStream(buffer.toByteArray()), out, "pdf");
+                } else {
+                    out = new FileOutputStream(filename + ".gv");
+
+                    printGraph(graph, name, out);
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            } finally {
+                if (out != null) {
+                    try {
+                        out.close();
+                    } catch (IOException e) {
+                    }
+                }
+            }
+        }
+    }
+
+    private static void printGraph(Graph graph, String name, OutputStream buffer) {
+        GraphvizPrinter printer = new GraphvizPrinter(buffer);
+        if (GraalOptions.OmitDOTFrameStates) {
+            printer.addOmittedClass(FrameState.class);
+        }
+        printer.addClassColor(StartNode.class, "snow3");
+        printer.addClassColor(LoopBegin.class, "skyblue");
+        printer.addClassColor(LoopEnd.class, "skyblue3");
+        printer.addClassColor(Unwind.class, "red");
+        printer.addClassColor(Return.class, "indianred1");
+        printer.begin(name);
+        printer.print(graph, true);
+        printer.end();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,441 @@
+/*
+ * 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.max.graal.compiler.debug;
+
+import java.io.*;
+import java.util.*;
+import java.util.AbstractMap.SimpleImmutableEntry;
+import java.util.Map.Entry;
+
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.schedule.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.compiler.util.LoopUtil.Loop;
+import com.oracle.max.graal.compiler.value.*;
+import com.oracle.max.graal.graph.*;
+
+/**
+ * Generates a representation of {@link Graph Graphs} that can be visualized and inspected with the <a
+ * href="http://kenai.com/projects/igv">Ideal Graph Visualizer</a>.
+ */
+public class IdealGraphPrinter {
+
+    private static class Edge {
+        final int from;
+        final int to;
+        final int fromIndex;
+        final int toIndex;
+
+        Edge(int from, int fromIndex, int to, int toIndex) {
+            this.from = from;
+            this.fromIndex = fromIndex;
+            this.to = to;
+            this.toIndex = toIndex;
+        }
+    }
+
+    private final HashSet<Class<?>> omittedClasses = new HashSet<Class<?>>();
+    private final PrintStream stream;
+    private final Set<Node> noBlockNodes = new HashSet<Node>();
+
+    /**
+     * Creates a new {@link IdealGraphPrinter} that writes to the specified output stream.
+     */
+    public IdealGraphPrinter(OutputStream stream) {
+        this.stream = new PrintStream(stream);
+    }
+
+    /**
+     * Adds a node class that is omitted in the output.
+     */
+    public void addOmittedClass(Class<?> clazz) {
+        omittedClasses.add(clazz);
+    }
+
+    /**
+     * Flushes any buffered output.
+     */
+    public void flush() {
+        stream.flush();
+    }
+
+    /**
+     * Starts a new graph document.
+     */
+    public void begin() {
+        stream.println("<graphDocument>");
+    }
+
+    /**
+     * Starts a new group of graphs with the given name, short name and method byte code index (BCI) as properties.
+     */
+    public void beginGroup(String name, String shortName, int bci) {
+        stream.println("<group>");
+        stream.printf(" <properties><p name='name'>%s</p><p name='origin'>Graal</p></properties>%n", escape(name));
+        stream.printf(" <method name='%s' shortName='%s' bci='%d'/>%n", escape(name), escape(shortName), bci);
+    }
+
+    /**
+     * Ends the current group.
+     */
+    public void endGroup() {
+        stream.println("</group>");
+    }
+
+    /**
+     * Finishes the graph document and flushes the output stream.
+     */
+    public void end() {
+        stream.println("</graphDocument>");
+        flush();
+    }
+
+    public void print(Graph graph, String title, boolean shortNames) {
+        print(graph, title, shortNames, Collections.<String, Object>emptyMap());
+    }
+
+    /**
+     * Prints an entire {@link Graph} with the specified title, optionally using short names for nodes.
+     */
+    public void print(Graph graph, String title, boolean shortNames, Map<String, Object> debugObjects) {
+        stream.printf(" <graph name='%s'>%n", escape(title));
+        noBlockNodes.clear();
+        IdentifyBlocksPhase schedule = null;
+        try {
+            schedule = new IdentifyBlocksPhase(true);
+            schedule.apply(graph, false, false);
+        } catch (Throwable t) {
+            // nothing to do here...
+            //t.printStackTrace();
+        }
+        List<Loop> loops = null;
+        try {
+            loops = LoopUtil.computeLoops(graph);
+        } catch (Throwable t) {
+            t.printStackTrace();
+        }
+
+        stream.println("  <nodes>");
+        List<Edge> edges = printNodes(graph, shortNames, schedule == null ? null : schedule.getNodeToBlock(), loops, debugObjects);
+        stream.println("  </nodes>");
+
+        stream.println("  <edges>");
+        for (Edge edge : edges) {
+            printEdge(edge);
+        }
+        stream.println("  </edges>");
+
+        if (schedule != null) {
+            stream.println("  <controlFlow>");
+            for (Block block : schedule.getBlocks()) {
+                printBlock(graph, block, schedule.getNodeToBlock());
+            }
+            printNoBlock();
+            stream.println("  </controlFlow>");
+        }
+
+        stream.println(" </graph>");
+        flush();
+    }
+
+    private List<Edge> printNodes(Graph graph, boolean shortNames, NodeMap<Block> nodeToBlock, List<Loop> loops, Map<String, Object> debugObjects) {
+        ArrayList<Edge> edges = new ArrayList<Edge>();
+        NodeBitMap loopExits = graph.createNodeBitMap();
+        if (loops != null) {
+            for (Loop loop : loops) {
+                loopExits.setUnion(loop.exits());
+            }
+        }
+
+        Map<Node, Set<Entry<String, Integer>>> colors = new HashMap<Node, Set<Entry<String, Integer>>>();
+        Map<Node, Set<Entry<String, String>>> colorsToString = new HashMap<Node, Set<Entry<String, String>>>();
+        Map<Node, Set<String>> bits = new HashMap<Node, Set<String>>();
+        if (debugObjects != null) {
+            for (Entry<String, Object> entry : debugObjects.entrySet()) {
+                String name = entry.getKey();
+                Object obj = entry.getValue();
+                if (obj instanceof NodeMap) {
+                    Map<Object, Integer> colorNumbers = new HashMap<Object, Integer>();
+                    int nextColor = 0;
+                    NodeMap<?> map = (NodeMap<?>) obj;
+                    for (Entry<Node, ?> mapEntry : map.entries()) {
+                        Node node = mapEntry.getKey();
+                        Object color = mapEntry.getValue();
+                        Integer colorNumber = colorNumbers.get(color);
+                        if (colorNumber == null) {
+                            colorNumber = nextColor++;
+                            colorNumbers.put(color, colorNumber);
+                        }
+                        Set<Entry<String, Integer>> nodeColors = colors.get(node);
+                        if (nodeColors == null) {
+                            nodeColors = new HashSet<Entry<String, Integer>>();
+                            colors.put(node, nodeColors);
+                        }
+                        nodeColors.add(new SimpleImmutableEntry<String, Integer>(name + "Color", colorNumber));
+                        Set<Entry<String, String>> nodeColorStrings = colorsToString.get(node);
+                        if (nodeColorStrings == null) {
+                            nodeColorStrings = new HashSet<Entry<String, String>>();
+                            colorsToString.put(node, nodeColorStrings);
+                        }
+                        nodeColorStrings.add(new SimpleImmutableEntry<String, String>(name, color.toString()));
+                    }
+                } else if (obj instanceof NodeBitMap) {
+                    NodeBitMap bitmap = (NodeBitMap) obj;
+                    for (Node node : bitmap) {
+                        Set<String> nodeBits = bits.get(node);
+                        if (nodeBits == null) {
+                            nodeBits = new HashSet<String>();
+                            bits.put(node, nodeBits);
+                        }
+                        nodeBits.add(name);
+                    }
+                }
+            }
+        }
+
+        for (Node node : graph.getNodes()) {
+            if (omittedClasses.contains(node.getClass())) {
+                continue;
+            }
+
+            stream.printf("   <node id='%d'><properties>%n", node.id());
+            stream.printf("    <p name='idx'>%d</p>%n", node.id());
+
+            Map<Object, Object> props = node.getDebugProperties();
+            if (!props.containsKey("name") || props.get("name").toString().trim().length() == 0) {
+                String name;
+                if (shortNames) {
+                    name = node.shortName();
+                } else {
+                    name = node.toString();
+                }
+                stream.printf("    <p name='name'>%s</p>%n", escape(name));
+            }
+            stream.printf("    <p name='class'>%s</p>%n", escape(node.getClass().getSimpleName()));
+            Block block = nodeToBlock == null ? null : nodeToBlock.get(node);
+            if (block != null) {
+                stream.printf("    <p name='block'>%d</p>%n", block.blockID());
+                if (!(node instanceof Phi || node instanceof FrameState || node instanceof Local || node instanceof LoopCounter) && !block.getInstructions().contains(node)) {
+                    stream.println("    <p name='notInOwnBlock'>true</p>");
+                }
+            } else {
+                stream.println("    <p name='block'>noBlock</p>");
+                noBlockNodes.add(node);
+            }
+            if (loopExits.isMarked(node)) {
+                stream.println("    <p name='loopExit'>true</p>");
+            }
+            StringBuilder sb = new StringBuilder();
+            if (loops != null) {
+                for (Loop loop : loops) {
+                    if (loop.nodes().isMarked(node)) {
+                        if (sb.length() > 0) {
+                            sb.append(", ");
+                        }
+                        sb.append(loop.loopBegin().id());
+                    }
+                }
+            }
+            if (sb.length() > 0) {
+                stream.printf("    <p name='loops'>%s</p>%n", sb);
+            }
+
+            Set<Entry<String, Integer>> nodeColors = colors.get(node);
+            if (nodeColors != null) {
+                for (Entry<String, Integer> color : nodeColors) {
+                    String name = color.getKey();
+                    Integer value = color.getValue();
+                    stream.printf("    <p name='%s'>%d</p>%n", name, value);
+                }
+            }
+            Set<Entry<String, String>> nodeColorStrings = colorsToString.get(node);
+            if (nodeColorStrings != null) {
+                for (Entry<String, String> color : nodeColorStrings) {
+                    String name = color.getKey();
+                    String value = color.getValue();
+                    stream.printf("    <p name='%s'>%s</p>%n", name, value);
+                }
+            }
+            Set<String> nodeBits = bits.get(node);
+            if (nodeBits != null) {
+                for (String bit : nodeBits) {
+                    stream.print("    <p name='");
+                    stream.print(bit);
+                    stream.println("'>true</p>");
+                }
+            }
+
+            for (Entry<Object, Object> entry : props.entrySet()) {
+                String key = entry.getKey().toString();
+                String value = entry.getValue() == null ? "null" : entry.getValue().toString();
+                stream.print("    <p name='");
+                stream.print(escape(key));
+                stream.print("'>");
+                stream.print(escape(value));
+                stream.println("</p>");
+            }
+
+            stream.println("   </properties></node>");
+
+            // successors
+            int fromIndex = 0;
+            for (Node successor : node.successors()) {
+                if (successor != Node.Null && !omittedClasses.contains(successor.getClass())) {
+                    edges.add(new Edge(node.id(), fromIndex, successor.id(), 0));
+                }
+                fromIndex++;
+            }
+
+            // inputs
+            int toIndex = 1;
+            for (Node input : node.inputs()) {
+                if (input != Node.Null && !omittedClasses.contains(input.getClass())) {
+                    edges.add(new Edge(input.id(), input.successors().size(), node.id(), toIndex));
+                }
+                toIndex++;
+            }
+        }
+
+        return edges;
+    }
+
+    private void printEdge(Edge edge) {
+        stream.printf("   <edge from='%d' fromIndex='%d' to='%d' toIndex='%d'/>%n", edge.from, edge.fromIndex, edge.to, edge.toIndex);
+    }
+
+    private void printBlock(Graph graph, Block block, NodeMap<Block> nodeToBlock) {
+        stream.printf("   <block name='%d'>%n", block.blockID());
+        stream.println("    <successors>");
+        for (Block sux : block.getSuccessors()) {
+            if (sux != null) {
+                stream.printf("     <successor name='%d'/>%n", sux.blockID());
+            }
+        }
+        stream.println("    </successors>");
+        stream.println("    <nodes>");
+
+        Set<Node> nodes = new HashSet<Node>(block.getInstructions());
+
+        if (nodeToBlock != null) {
+            for (Node n : graph.getNodes()) {
+                Block blk = nodeToBlock.get(n);
+                if (blk == block) {
+                    nodes.add(n);
+                }
+            }
+        }
+
+        if (nodes.size() > 0) {
+            // if this is the first block: add all locals to this block
+            if (block.getInstructions().size() > 0  && block.getInstructions().get(0) == graph.start()) {
+                for (Node node : graph.getNodes()) {
+                    if (node instanceof Local) {
+                        nodes.add(node);
+                    }
+                }
+            }
+
+            // add all framestates and phis to their blocks
+            for (Node node : block.getInstructions()) {
+                if (node instanceof StateSplit && ((StateSplit) node).stateAfter() != null) {
+                    nodes.add(((StateSplit) node).stateAfter());
+                }
+                if (node instanceof Merge) {
+                    for (Node usage : node.usages()) {
+                        if (usage instanceof Phi || usage instanceof LoopCounter) {
+                            nodes.add(usage);
+                        }
+                    }
+                }
+            }
+
+            for (Node node : nodes) {
+                if (!omittedClasses.contains(node.getClass())) {
+                    stream.printf("     <node id='%d'/>%n", node.id());
+                }
+            }
+        }
+        stream.println("    </nodes>");
+        stream.printf("   </block>%n", block.blockID());
+    }
+
+    private void printNoBlock() {
+        if (!noBlockNodes.isEmpty()) {
+            stream.printf("   <block name='noBlock'>%n");
+            stream.printf("    <nodes>%n");
+            for (Node node : noBlockNodes) {
+                stream.printf("     <node id='%d'/>%n", node.id());
+            }
+            stream.printf("    </nodes>%n");
+            stream.printf("   </block>%n");
+        }
+    }
+
+    private String escape(String s) {
+        StringBuilder str = null;
+        for (int i = 0; i < s.length(); i++) {
+            char c = s.charAt(i);
+            switch (c) {
+                case '&':
+                case '<':
+                case '>':
+                case '"':
+                case '\'':
+                    if (str == null) {
+                        str = new StringBuilder();
+                        str.append(s, 0, i);
+                    }
+                    switch(c) {
+                        case '&':
+                            str.append("&amp;");
+                            break;
+                        case '<':
+                            str.append("&lt;");
+                            break;
+                        case '>':
+                            str.append("&gt;");
+                            break;
+                        case '"':
+                            str.append("&quot;");
+                            break;
+                        case '\'':
+                            str.append("&apos;");
+                            break;
+                        default:
+                            assert false;
+                    }
+                    break;
+                default:
+                    if (str != null) {
+                        str.append(c);
+                    }
+                    break;
+            }
+        }
+        if (str == null) {
+            return s;
+        } else {
+            return str.toString();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinterObserver.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,179 @@
+/*
+ * 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.max.graal.compiler.debug;
+
+import java.io.*;
+import java.net.*;
+import java.util.regex.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.observer.*;
+import com.oracle.max.graal.compiler.value.*;
+import com.oracle.max.graal.graph.*;
+
+/**
+ * Observes compilation events and uses {@link IdealGraphPrinter} to generate a graph representation that can be
+ * inspected with the <a href="http://kenai.com/projects/igv">Ideal Graph Visualizer</a>.
+ *
+ * @author Peter Hofer
+ */
+public class IdealGraphPrinterObserver implements CompilationObserver {
+
+    private static final Pattern INVALID_CHAR = Pattern.compile("[^A-Za-z0-9_.-]");
+
+    private final String host;
+    private final int port;
+
+    private IdealGraphPrinter printer;
+    private OutputStream stream;
+    private Socket socket;
+
+    /**
+     * Creates a new {@link IdealGraphPrinterObserver} that writes output to a file named after the compiled method.
+     */
+    public IdealGraphPrinterObserver() {
+        this(null, -1);
+    }
+
+    /**
+     * Creates a new {@link IdealGraphPrinterObserver} that sends output to a remove IdealGraphVisualizer instance.
+     */
+    public IdealGraphPrinterObserver(String host, int port) {
+        this.host = host;
+        this.port = port;
+    }
+
+    @Override
+    public void compilationStarted(CompilationEvent event) {
+        assert (stream == null && printer == null);
+
+        if ((!TTY.isSuppressed() && GraalOptions.Plot) || (GraalOptions.PlotOnError && event.isErrorEvent())) {
+            String name = event.getMethod().holder().name();
+            name = name.substring(1, name.length() - 1).replace('/', '.');
+            name = name + "." + event.getMethod().name();
+
+            if (host != null) {
+                openNetworkPrinter(name);
+            } else {
+                openFilePrinter(name);
+            }
+        }
+    }
+
+    private void openFilePrinter(String name) {
+        String filename = name + ".igv.xml";
+        filename = INVALID_CHAR.matcher(filename).replaceAll("_");
+
+        try {
+            stream = new FileOutputStream(filename);
+            printer = new IdealGraphPrinter(stream);
+            if (GraalOptions.OmitDOTFrameStates) {
+                printer.addOmittedClass(FrameState.class);
+            }
+            printer.begin();
+            printer.beginGroup(name, name, -1);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private void openNetworkPrinter(String name) {
+        try {
+            socket = new Socket(host, port);
+            if (socket.getInputStream().read() == 'y') {
+                stream = new BufferedOutputStream(socket.getOutputStream(), 0x4000);
+            } else {
+                // server currently does not accept any input
+                socket.close();
+                socket = null;
+                return;
+            }
+
+            printer = new IdealGraphPrinter(new BufferedOutputStream(stream));
+            if (GraalOptions.OmitDOTFrameStates) {
+                printer.addOmittedClass(FrameState.class);
+            }
+            printer.begin();
+            printer.beginGroup(name, name, -1);
+            printer.flush();
+            if (socket.getInputStream().read() != 'y') {
+                // server declines input for this method
+                socket.close();
+                socket = null;
+                stream = null;
+                printer = null;
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+
+            if (socket != null) {
+                try {
+                    socket.close();
+                } catch (IOException ioe) {
+                }
+                socket = null;
+            }
+            stream = null;
+            printer = null;
+        }
+    }
+
+    @Override
+    public void compilationEvent(CompilationEvent event) {
+        boolean lazyStart = false;
+        if (printer == null && event.isErrorEvent()) {
+            this.compilationStarted(event);
+            lazyStart = true;
+        }
+        if (printer != null && event.getGraph() != null && event.isHIRValid()) {
+            Graph graph = event.getGraph();
+            printer.print(graph, event.getLabel(), true, event.getDebugObjects());
+        }
+        if (lazyStart) {
+            this.compilationFinished(event);
+        }
+    }
+
+    @Override
+    public void compilationFinished(CompilationEvent event) {
+        if (printer != null) {
+            try {
+                printer.endGroup();
+                printer.end();
+
+                if (socket != null) {
+                    socket.close(); // also closes stream
+                } else {
+                    stream.close();
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            } finally {
+                printer = null;
+                stream = null;
+                socket = null;
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/InstructionPrinter.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.debug;
+
+import static com.oracle.max.graal.compiler.debug.InstructionPrinter.InstructionLineColumn.*;
+
+import com.oracle.max.graal.compiler.ir.*;
+
+/**
+ * A {@link ValueVisitor} for {@linkplain #printInstruction(Value) printing}
+ * an {@link FixedNodeWithNext} as an expression or statement.
+ *
+ * @author Doug Simon
+ */
+public class InstructionPrinter {
+
+
+    /**
+     * The columns printed in a tabulated instruction
+     * {@linkplain InstructionPrinter#printInstructionListing(Value) listing}.
+     */
+    public enum InstructionLineColumn {
+        /**
+         * The instruction's bytecode index.
+         */
+        BCI(2, "bci"),
+
+        /**
+         * The instruction's use count.
+         */
+        USE(7, "use"),
+
+        /**
+         * The instruction as a {@linkplain com.oracle.max.graal.compiler.util.Util#valueString(com.oracle.max.graal.compiler.ir.Value) value}.
+         */
+        VALUE(12, "tid"),
+
+        /**
+         * The instruction formatted as an expression or statement.
+         */
+        INSTRUCTION(19, "instr"),
+
+        END(60, "");
+
+        final int position;
+        final String label;
+
+        private InstructionLineColumn(int position, String label) {
+            this.position = position;
+            this.label = label;
+        }
+
+        /**
+         * Prints this column's label to a given stream after padding the stream with '_' characters
+         * until its {@linkplain LogStream#position() position} is equal to this column's position.
+         * @param out the print stream
+         */
+        public void printLabel(LogStream out) {
+            out.fillTo(position + out.indentationLevel(), '_');
+            out.print(label);
+        }
+
+        /**
+         * Prints space characters to a given stream until its {@linkplain LogStream#position() position}
+         * is equal to this column's position.
+         * @param out the print stream
+         */
+        public void advance(LogStream out) {
+            out.fillTo(position + out.indentationLevel(), ' ');
+        }
+    }
+
+    private final LogStream out;
+
+    public InstructionPrinter(LogStream out) {
+        this.out = out;
+    }
+
+    public LogStream out() {
+        return out;
+    }
+
+    /**
+     * Prints a given instruction as an expression or statement.
+     *
+     * @param instruction the instruction to print
+     */
+    public void printInstruction(Value instruction) {
+        instruction.print(out);
+    }
+
+
+    /**
+     * Prints a header for the tabulated data printed by {@link #printInstructionListing(Value)}.
+     */
+    public void printInstructionListingHeader() {
+        BCI.printLabel(out);
+        USE.printLabel(out);
+        VALUE.printLabel(out);
+        INSTRUCTION.printLabel(out);
+        END.printLabel(out);
+        out.println();
+    }
+
+    /**
+     * Prints an instruction listing on one line. The instruction listing is composed of the
+     * columns specified by {@link InstructionLineColumn}.
+     *
+     * @param instruction the instruction to print
+     */
+    public void printInstructionListing(Value instruction) {
+        int indentation = out.indentationLevel();
+        out.fillTo(BCI.position + indentation, ' ').
+             print(0).
+             fillTo(USE.position + indentation, ' ').
+             print("0").
+             fillTo(VALUE.position + indentation, ' ').
+             print(instruction).
+             fillTo(INSTRUCTION.position + indentation, ' ');
+        printInstruction(instruction);
+        String flags = instruction.flagsToString();
+        if (!flags.isEmpty()) {
+            out.print("  [flags: " + flags + "]");
+        }
+        if (instruction instanceof StateSplit) {
+            out.print("  [state: " + ((StateSplit) instruction).stateAfter() + "]");
+        }
+        out.println();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/LogStream.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,494 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.debug;
+
+import java.io.*;
+import java.util.*;
+
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.util.*;
+
+/**
+ * A utility for printing compiler debug and informational output to an output stream.
+ *
+ * A {@link LogStream} instance maintains an internal buffer that is flushed to the underlying
+ * output stream every time one of the {@code println} methods is invoked, or a newline character
+ * ({@code '\n'}) is written.
+ *
+ * All of the {@code print} and {@code println} methods return the {code LogStream} instance
+ * on which they were invoked. This allows chaining of these calls to mitigate use of String
+ * concatenation by the caller.
+ *
+ * A {@code LogStream} maintains a current {@linkplain #indentationLevel() indentation} level.
+ * Each line of output written to this stream has {@code n} spaces prefixed to it where
+ * {@code n} is the value that would be returned by {@link #indentationLevel()} when the first
+ * character of a new line is written.
+ *
+ * A {@code LogStream} maintains a current {@linkplain #position() position} for the current
+ * line being written. This position can be advanced to a specified position by
+ * {@linkplain #fillTo(int, char) filling} this stream with a given character.
+ *
+ * @author Doug Simon
+ */
+public class LogStream {
+
+    /**
+     * Null output stream that simply swallows any output sent to it.
+     */
+    public static final LogStream SINK = new LogStream();
+
+    private LogStream() {
+        this.ps = null;
+        this.lineBuffer = null;
+    }
+
+    /**
+     * The output stream to which this log stream writes.
+     */
+    private final PrintStream ps;
+
+    private final StringBuilder lineBuffer;
+    private int indentationLevel;
+    private char indentation = ' ';
+    private boolean indentationDisabled;
+
+    /**
+     * The system dependent line separator.
+     */
+    public static final String LINE_SEPARATOR = System.getProperty("line.separator");
+
+    /**
+     * Creates a new log stream.
+     *
+     * @param os the underlying output stream to which prints are sent
+     */
+    public LogStream(OutputStream os) {
+        ps = os instanceof PrintStream ? (PrintStream) os : new PrintStream(os);
+        lineBuffer = new StringBuilder(100);
+    }
+
+    /**
+     * Creates a new log stream that shares the same {@linkplain #ps output stream} as a given {@link LogStream}.
+     *
+     * @param log a LogStream whose output stream is shared with this one
+     */
+    public LogStream(LogStream log) {
+        ps = log.ps;
+        lineBuffer = new StringBuilder(100);
+    }
+
+    /**
+     * Prepends {@link #indentation} to the current output line until its write position is equal to the
+     * current {@linkplain #indentationLevel()} level.
+     */
+    private void indent() {
+        if (ps != null) {
+            if (!indentationDisabled && indentationLevel != 0) {
+                while (lineBuffer.length() < indentationLevel) {
+                    lineBuffer.append(indentation);
+                }
+            }
+        }
+    }
+
+    private LogStream flushLine(boolean withNewline) {
+        if (ps != null) {
+            if (withNewline) {
+                lineBuffer.append(LINE_SEPARATOR);
+            } else {
+                assert lineBuffer.indexOf(LINE_SEPARATOR, lineBuffer.length() - LINE_SEPARATOR.length()) != -1;
+            }
+            ps.print(lineBuffer.toString());
+            ps.flush();
+            lineBuffer.setLength(0);
+        }
+        return this;
+    }
+
+    /**
+     * Flushes the stream. This is done by terminating the current line if it is not at position 0
+     * and then flushing the underlying output stream.
+     */
+    public void flush() {
+        if (ps != null) {
+            if (lineBuffer.length() != 0) {
+                flushLine(true);
+            }
+            ps.flush();
+        }
+    }
+
+    /**
+     * Gets the current column position of this log stream.
+     *
+     * @return the current column position of this log stream
+     */
+    public int position() {
+        return lineBuffer == null ? 0 : lineBuffer.length();
+
+    }
+
+    /**
+     * Gets the current indentation level for this log stream.
+     *
+     * @return the current indentation level for this log stream.
+     */
+    public int indentationLevel() {
+        return indentationLevel;
+    }
+
+    /**
+     * Adjusts the current indentation level of this log stream.
+     *
+     * @param delta
+     */
+    public void adjustIndentation(int delta) {
+        if (delta < 0) {
+            indentationLevel = Math.max(0, indentationLevel + delta);
+        } else {
+            indentationLevel += delta;
+        }
+    }
+
+    /**
+     * Gets the current indentation character of this log stream.
+     */
+    public char indentation() {
+        return indentation;
+    }
+
+    public void disableIndentation() {
+        indentationDisabled = true;
+    }
+
+    public void enableIndentation() {
+        indentationDisabled = false;
+    }
+
+    /**
+     * Sets the character used for indentation.
+     */
+    public void setIndentation(char c) {
+        indentation = c;
+    }
+
+    /**
+     * Advances this stream's {@linkplain #position() position} to a given position by
+     * repeatedly appending a given character as necessary.
+     *
+     * @param position the position to which this stream's position will be advanced
+     * @param filler the character used to pad the stream
+     */
+    public LogStream fillTo(int position, char filler) {
+        if (ps != null) {
+            indent();
+            while (lineBuffer.length() < position) {
+                lineBuffer.append(filler);
+            }
+        }
+        return this;
+    }
+
+    /**
+     * Writes a boolean value to this stream as {@code "true"} or {@code "false"}.
+     *
+     * @param b the value to be printed
+     * @return this {@link LogStream} instance
+     */
+    public LogStream print(boolean b) {
+        if (ps != null) {
+            indent();
+            lineBuffer.append(b);
+        }
+        return this;
+    }
+
+    /**
+     * Writes a boolean value to this stream followed by a {@linkplain #LINE_SEPARATOR line separator}.
+     *
+     * @param b the value to be printed
+     * @return this {@link LogStream} instance
+     */
+    public LogStream println(boolean b) {
+        if (ps != null) {
+            indent();
+            lineBuffer.append(b);
+            return flushLine(true);
+        }
+        return this;
+    }
+
+    /**
+     * Writes a character value to this stream.
+     *
+     * @param c the value to be printed
+     * @return this {@link LogStream} instance
+     */
+    public LogStream print(char c) {
+        if (ps != null) {
+            indent();
+            lineBuffer.append(c);
+            if (c == '\n') {
+                if (lineBuffer.indexOf(LINE_SEPARATOR, lineBuffer.length() - LINE_SEPARATOR.length()) != -1) {
+                    flushLine(false);
+                }
+            }
+        }
+        return this;
+    }
+
+    /**
+     * Writes a character value to this stream followed by a {@linkplain #LINE_SEPARATOR line separator}.
+     *
+     * @param c the value to be printed
+     * @return this {@link LogStream} instance
+     */
+    public LogStream println(char c) {
+        if (ps != null) {
+            indent();
+            lineBuffer.append(c);
+            flushLine(true);
+        }
+        return this;
+    }
+
+    /**
+     * Prints an int value.
+     *
+     * @param i the value to be printed
+     * @return this {@link LogStream} instance
+     */
+    public LogStream print(int i) {
+        if (ps != null) {
+            indent();
+            lineBuffer.append(i);
+        }
+        return this;
+    }
+
+    /**
+     * Writes an int value to this stream followed by a {@linkplain #LINE_SEPARATOR line separator}.
+     *
+     * @param i the value to be printed
+     * @return this {@link LogStream} instance
+     */
+    public LogStream println(int i) {
+        if (ps != null) {
+            indent();
+            lineBuffer.append(i);
+            return flushLine(true);
+        }
+        return this;
+    }
+
+    /**
+     * Writes a float value to this stream.
+     *
+     * @param f the value to be printed
+     * @return this {@link LogStream} instance
+     */
+    public LogStream print(float f) {
+        if (ps != null) {
+            indent();
+            lineBuffer.append(f);
+        }
+        return this;
+    }
+
+    /**
+     * Writes a float value to this stream followed by a {@linkplain #LINE_SEPARATOR line separator}.
+     *
+     * @param f the value to be printed
+     * @return this {@link LogStream} instance
+     */
+    public LogStream println(float f) {
+        if (ps != null) {
+            indent();
+            lineBuffer.append(f);
+            return flushLine(true);
+        }
+        return this;
+    }
+
+    /**
+     * Writes a long value to this stream.
+     *
+     * @param l the value to be printed
+     * @return this {@link LogStream} instance
+     */
+    public LogStream print(long l) {
+        if (ps != null) {
+            indent();
+            lineBuffer.append(l);
+        }
+        return this;
+    }
+
+    /**
+     * Writes a long value to this stream followed by a {@linkplain #LINE_SEPARATOR line separator}.
+     *
+     * @param l the value to be printed
+     * @return this {@link LogStream} instance
+     */
+    public LogStream println(long l) {
+        if (ps != null) {
+            indent();
+            lineBuffer.append(l);
+            return flushLine(true);
+        }
+        return this;
+    }
+
+    /**
+     * Writes a double value to this stream.
+     *
+     * @param d the value to be printed
+     * @return this {@link LogStream} instance
+     */
+    public LogStream print(double d) {
+        if (ps != null) {
+            indent();
+            lineBuffer.append(d);
+        }
+        return this;
+    }
+
+    /**
+     * Writes a double value to this stream followed by a {@linkplain #LINE_SEPARATOR line separator}.
+     *
+     * @param d the value to be printed
+     * @return this {@link LogStream} instance
+     */
+    public LogStream println(double d) {
+        if (ps != null) {
+            indent();
+            lineBuffer.append(d);
+            return flushLine(true);
+        }
+        return this;
+    }
+
+    /**
+     * Writes a {@code String} value to this stream. This method ensures that the {@linkplain #position() position}
+     * of this stream is updated correctly with respect to any {@linkplain #LINE_SEPARATOR line separators}
+     * present in {@code s}.
+     *
+     * @param s the value to be printed
+     * @return this {@link LogStream} instance
+     */
+    public LogStream print(String s) {
+        if (ps != null) {
+            if (s == null) {
+                indent();
+                lineBuffer.append(s);
+                return this;
+            }
+
+            int index = 0;
+            int next = s.indexOf(LINE_SEPARATOR, index);
+            while (index < s.length()) {
+                indent();
+                if (next > index) {
+                    lineBuffer.append(s.substring(index, next));
+                    flushLine(true);
+                    index = next + LINE_SEPARATOR.length();
+                    next = s.indexOf(LINE_SEPARATOR, index);
+                } else {
+                    lineBuffer.append(s.substring(index));
+                    break;
+                }
+            }
+        }
+        return this;
+    }
+
+    /**
+     * Writes a {@code String} value to this stream followed by a {@linkplain #LINE_SEPARATOR line separator}.
+     *
+     * @param s the value to be printed
+     * @return this {@link LogStream} instance
+     */
+    public LogStream println(String s) {
+        if (ps != null) {
+            print(s);
+            flushLine(true);
+        }
+        return this;
+    }
+
+    /**
+     * Writes a formatted string to this stream.
+     *
+     * @param format a format string as described in {@link String#format(String, Object...)}
+     * @param args the arguments to be formatted
+     * @return this {@link LogStream} instance
+     */
+    public LogStream printf(String format, Object... args) {
+        if (ps != null) {
+            print(String.format(Locale.ENGLISH, format, args));
+        }
+        return this;
+    }
+
+    /**
+     * Writes an instruction formatted as a {@linkplain com.oracle.max.graal.compiler.util.Util#valueString(com.oracle.max.graal.compiler.ir.Value) value} to this stream.
+     *
+     * @param value the instruction to print
+     * @return this {@code LogStream} instance
+     */
+    public LogStream print(Value value) {
+        if (ps != null) {
+            indent();
+            lineBuffer.append(Util.valueString(value));
+        }
+        return this;
+    }
+
+    /**
+     * Writes an instruction formatted as a {@linkplain com.oracle.max.graal.compiler.util.Util#valueString(com.oracle.max.graal.compiler.ir.Value) value} to this stream
+     * followed by a {@linkplain #LINE_SEPARATOR line separator}.
+     *
+     * @param value the instruction to print
+     * @return this {@code LogStream} instance
+     */
+    public LogStream println(Value value) {
+        if (ps != null) {
+            print(value);
+            flushLine(true);
+        }
+        return this;
+    }
+
+    /**
+     * Writes a {@linkplain #LINE_SEPARATOR line separator} to this stream.
+     *
+     * @return this {@code LogStream} instance
+     */
+    public LogStream println() {
+        if (ps != null) {
+            indent();
+            flushLine(true);
+        }
+        return this;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/TTY.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.debug;
+
+import java.io.*;
+import java.util.regex.*;
+
+import com.oracle.max.graal.compiler.util.*;
+
+
+/**
+ * A collection of static methods for printing debug and informational output to a global {@link LogStream}.
+ * The output can be (temporarily) suppressed per thread through use of a {@linkplain Filter filter}.
+ *
+ * @author Doug Simon
+ */
+public class TTY {
+
+    /**
+     * Support for thread-local suppression of {@link TTY}.
+     *
+     * @author Doug Simon
+     */
+    public static class Filter {
+        private LogStream previous;
+        private final Thread thread = Thread.currentThread();
+
+        /**
+         * Creates an object that will suppress {@link TTY} for the current thread if the given filter does not
+         * {@linkplain #matches(String, Object) match} the given object. To revert the suppression state to how it was
+         * before this call, the {@link #remove()} method must be called on the suppression object.
+         *
+         * @param filter the pattern for matching. If {@code null}, then the match is successful. If it starts with "~",
+         *            then a regular expression {@linkplain Pattern#matches(String, CharSequence) match} is performed
+         *            where the regular expression is specified by {@code filter} without the "~" prefix. Otherwise, a
+         *            simple {@linkplain String#contains(CharSequence) substring} match is performed where {@code
+         *            filter} is the substring used.
+         * @param object an object whose {@linkplain Object#toString() string} value is matched against {@code filter}
+         */
+        public Filter(String filter, Object object) {
+            boolean suppressed = false;
+            if (filter != null) {
+                String input = object.toString();
+                if (filter.startsWith("~")) {
+                    suppressed = !Pattern.matches(filter.substring(1), input);
+                } else {
+                    suppressed = !input.contains(filter);
+                }
+                if (suppressed) {
+                    previous = out();
+                    out.set(LogStream.SINK);
+                }
+            }
+        }
+
+        /**
+         * Reverts the suppression state of {@link TTY} to how it was before this object was constructed.
+         */
+        public void remove() {
+            assert thread == Thread.currentThread();
+            if (previous != null) {
+                out.set(previous);
+            }
+        }
+    }
+
+    public static final String GRAAL_TTY_LOG_FILE_PROPERTY = "graal.tty.file";
+
+    private static final LogStream log;
+    static {
+        PrintStream out = System.out;
+        String value = System.getProperty(GRAAL_TTY_LOG_FILE_PROPERTY);
+        if (value != null) {
+            try {
+                out = new PrintStream(new FileOutputStream(value));
+            } catch (FileNotFoundException e) {
+                Util.warning("Could not open log file " + value + ": " + e);
+            }
+        }
+        log = new LogStream(out);
+    }
+
+    private static final ThreadLocal<LogStream> out = new ThreadLocal<LogStream>() {
+        @Override
+        protected LogStream initialValue() {
+            return log;
+        };
+    };
+
+    public static boolean isSuppressed() {
+        return out.get() == LogStream.SINK;
+    }
+
+    /**
+     * Gets the thread-local log stream to which the static methods of this class send their output.
+     * This will either be a global log stream or the global {@linkplain LogStream#SINK sink} depending
+     * on whether any suppression {@linkplain Filter filters} are in effect for the current thread.
+     */
+    public static LogStream out() {
+        return out.get();
+    }
+
+    /**
+     * @see LogStream#print(String)
+     */
+    public static void print(String s) {
+        out().print(s);
+    }
+
+    /**
+     * @see LogStream#print(int)
+     */
+    public static void print(int i) {
+        out().print(i);
+    }
+
+    /**
+     * @see LogStream#print(long)
+     */
+    public static void print(long i) {
+        out().print(i);
+    }
+
+    /**
+     * @see LogStream#print(char)
+     */
+    public static void print(char c) {
+        out().print(c);
+    }
+
+    /**
+     * @see LogStream#print(boolean)
+     */
+    public static void print(boolean b) {
+        out().print(b);
+    }
+
+    /**
+     * @see LogStream#print(double)
+     */
+    public static void print(double d) {
+        out().print(d);
+    }
+
+    /**
+     * @see LogStream#print(float)
+     */
+    public static void print(float f) {
+        out().print(f);
+    }
+
+    /**
+     * @see LogStream#println(String)
+     */
+    public static void println(String s) {
+        out().println(s);
+    }
+
+    /**
+     * @see LogStream#println()
+     */
+    public static void println() {
+        out().println();
+    }
+
+    /**
+     * @see LogStream#println(int)
+     */
+    public static void println(int i) {
+        out().println(i);
+    }
+
+    /**
+     * @see LogStream#println(long)
+     */
+    public static void println(long l) {
+        out().println(l);
+    }
+
+    /**
+     * @see LogStream#println(char)
+     */
+    public static void println(char c) {
+        out().println(c);
+    }
+
+    /**
+     * @see LogStream#println(boolean)
+     */
+    public static void println(boolean b) {
+        out().println(b);
+    }
+
+    /**
+     * @see LogStream#println(double)
+     */
+    public static void println(double d) {
+        out().println(d);
+    }
+
+    /**
+     * @see LogStream#println(float)
+     */
+    public static void println(float f) {
+        out().println(f);
+    }
+
+    public static void print(String format, Object... args) {
+        out().printf(format, args);
+    }
+
+    public static void println(String format, Object... args) {
+        out().printf(format + "%n", args);
+    }
+
+    public static void fillTo(int i) {
+        out().fillTo(i, ' ');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/package-info.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/**
+ * A collection of debugging aids for Graal development.
+ */
+package com.oracle.max.graal.compiler.debug;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,1866 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.gen;
+
+import static com.sun.cri.bytecode.Bytecodes.*;
+import static com.sun.cri.bytecode.Bytecodes.MemoryBarriers.*;
+import static com.sun.cri.ci.CiCallingConvention.Type.*;
+import static com.sun.cri.ci.CiValue.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.oracle.max.asm.*;
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.alloc.*;
+import com.oracle.max.graal.compiler.alloc.OperandPool.VariableFlag;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.globalstub.*;
+import com.oracle.max.graal.compiler.graph.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.ir.Deoptimize.DeoptAction;
+import com.oracle.max.graal.compiler.ir.Phi.PhiType;
+import com.oracle.max.graal.compiler.lir.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.compiler.value.*;
+import com.oracle.max.graal.compiler.value.FrameState.ValueProcedure;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.bytecode.Bytecodes.MemoryBarriers;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+import com.sun.cri.ri.RiType.Representation;
+import com.sun.cri.xir.CiXirAssembler.XirConstant;
+import com.sun.cri.xir.CiXirAssembler.XirInstruction;
+import com.sun.cri.xir.CiXirAssembler.XirOperand;
+import com.sun.cri.xir.CiXirAssembler.XirParameter;
+import com.sun.cri.xir.CiXirAssembler.XirRegister;
+import com.sun.cri.xir.CiXirAssembler.XirTemp;
+import com.sun.cri.xir.*;
+
+/**
+ * This class traverses the HIR instructions and generates LIR instructions from them.
+ */
+public abstract class LIRGenerator extends ValueVisitor {
+
+    /**
+     * Helper class for inserting memory barriers as necessary to implement the Java Memory Model
+     * with respect to volatile field accesses.
+     *
+     * @see MemoryBarriers
+     */
+    class VolatileMemoryAccess {
+        /**
+         * Inserts any necessary memory barriers before a volatile write as required by the JMM.
+         */
+        void preVolatileWrite() {
+            int barriers = compilation.target.arch.requiredBarriers(JMM_PRE_VOLATILE_WRITE);
+            if (compilation.target.isMP && barriers != 0) {
+                lir.membar(barriers);
+            }
+        }
+
+        /**
+         * Inserts any necessary memory barriers after a volatile write as required by the JMM.
+         */
+        void postVolatileWrite() {
+            int barriers = compilation.target.arch.requiredBarriers(JMM_POST_VOLATILE_WRITE);
+            if (compilation.target.isMP && barriers != 0) {
+                lir.membar(barriers);
+            }
+        }
+
+        /**
+         * Inserts any necessary memory barriers before a volatile read as required by the JMM.
+         */
+        void preVolatileRead() {
+            int barriers = compilation.target.arch.requiredBarriers(JMM_PRE_VOLATILE_READ);
+            if (compilation.target.isMP && barriers != 0) {
+                lir.membar(barriers);
+            }
+        }
+
+        /**
+         * Inserts any necessary memory barriers after a volatile read as required by the JMM.
+         */
+        void postVolatileRead() {
+            // Ensure field's data is loaded before any subsequent loads or stores.
+            int barriers = compilation.target.arch.requiredBarriers(LOAD_LOAD | LOAD_STORE);
+            if (compilation.target.isMP && barriers != 0) {
+                lir.membar(barriers);
+            }
+        }
+    }
+
+    /**
+     * Forces the result of a given instruction to be available in a given register,
+     * inserting move instructions if necessary.
+     *
+     * @param instruction an instruction that produces a {@linkplain Value#operand() result}
+     * @param register the {@linkplain CiRegister} in which the result of {@code instruction} must be available
+     * @return {@code register} as an operand
+     */
+    protected CiValue force(Value instruction, CiRegister register) {
+        return force(instruction, register.asValue(instruction.kind));
+    }
+
+    /**
+     * Forces the result of a given instruction to be available in a given operand,
+     * inserting move instructions if necessary.
+     *
+     * @param instruction an instruction that produces a {@linkplain Value#operand() result}
+     * @param operand the operand in which the result of {@code instruction} must be available
+     * @return {@code operand}
+     */
+    protected CiValue force(Value instruction, CiValue operand) {
+        CiValue result = makeOperand(instruction);
+        if (result != operand) {
+            assert result.kind != CiKind.Illegal;
+            if (!compilation.archKindsEqual(result.kind, operand.kind)) {
+                // moves between different types need an intervening spill slot
+                CiValue tmp = forceToSpill(result, operand.kind, false);
+                lir.move(tmp, operand);
+            } else {
+                lir.move(result, operand);
+            }
+        }
+        return operand;
+    }
+
+    public CiValue load(Value val) {
+        CiValue result = makeOperand(val);
+        if (!result.isVariableOrRegister()) {
+            CiVariable operand = newVariable(val.kind);
+            lir.move(result, operand);
+            return operand;
+        }
+        return result;
+    }
+
+    // the range of values in a lookupswitch or tableswitch statement
+    private static final class SwitchRange {
+        final int lowKey;
+        int highKey;
+        final LIRBlock sux;
+
+        SwitchRange(int lowKey, LIRBlock sux) {
+            this.lowKey = lowKey;
+            this.highKey = lowKey;
+            this.sux = sux;
+        }
+    }
+
+    protected final GraalCompilation compilation;
+    protected final IR ir;
+    protected final XirSupport xirSupport;
+    protected final RiXirGenerator xir;
+    protected final boolean isTwoOperand;
+
+    private LIRBlock currentBlock;
+
+    public final OperandPool operands;
+
+    private Value currentInstruction;
+    private Value lastInstructionPrinted; // Debugging only
+
+    private List<CiConstant> constants;
+    private List<CiVariable> variablesForConstants;
+    protected LIRList lir;
+    final VolatileMemoryAccess vma;
+    private ArrayList<DeoptimizationStub> deoptimizationStubs;
+    private FrameState lastState;
+
+    public LIRGenerator(GraalCompilation compilation) {
+        this.compilation = compilation;
+        this.ir = compilation.hir();
+        this.xir = compilation.compiler.xir;
+        this.xirSupport = new XirSupport();
+        this.isTwoOperand = compilation.target.arch.twoOperandMode();
+        this.vma = new VolatileMemoryAccess();
+
+        constants = new ArrayList<CiConstant>();
+        variablesForConstants = new ArrayList<CiVariable>();
+
+        this.operands = new OperandPool(compilation.target);
+    }
+
+    public CiTarget target() {
+        return compilation.target;
+    }
+
+    public LIRList lir() {
+        return lir;
+    }
+
+    public ArrayList<DeoptimizationStub> deoptimizationStubs() {
+        return deoptimizationStubs;
+    }
+
+    private void addDeoptimizationStub(DeoptimizationStub stub) {
+        if (deoptimizationStubs == null) {
+            deoptimizationStubs = new ArrayList<LIRGenerator.DeoptimizationStub>();
+        }
+        deoptimizationStubs.add(stub);
+    }
+
+    public static class DeoptimizationStub {
+        public final Label label = new Label();
+        public final LIRDebugInfo info;
+        public final DeoptAction action;
+
+        public DeoptimizationStub(DeoptAction action, FrameState state) {
+            this.action = action;
+            info = new LIRDebugInfo(state);
+        }
+    }
+
+    public void doBlock(LIRBlock block) {
+        blockDoProlog(block);
+        this.currentBlock = block;
+
+        if (GraalOptions.TraceLIRGeneratorLevel >= 1) {
+            TTY.println("BEGIN Generating LIR for block B" + block.blockID());
+        }
+
+        if (block == ir.startBlock) {
+            XirSnippet prologue = xir.genPrologue(null, compilation.method);
+            if (prologue != null) {
+                emitXir(prologue, null, null, null, false);
+            }
+            FrameState fs = setOperandsForLocals();
+            if (GraalOptions.TraceLIRGeneratorLevel >= 2) {
+                TTY.println("STATE CHANGE (setOperandsForLocals)");
+                if (GraalOptions.TraceLIRGeneratorLevel >= 3) {
+                    TTY.println(fs.toString());
+                }
+            }
+            lastState = fs;
+        } else if (block.blockPredecessors().size() > 1) {
+            if (GraalOptions.TraceLIRGeneratorLevel >= 2) {
+                TTY.println("STATE RESET");
+            }
+            lastState = null;
+        }  else if (block.blockPredecessors().size() == 1) {
+            LIRBlock pred = block.blockPredecessors().get(0);
+            FrameState fs = pred.lastState();
+            assert fs != null : "block B" + block.blockID() + " pred block B" + pred.blockID();
+            if (GraalOptions.TraceLIRGeneratorLevel >= 2) {
+                TTY.println("STATE CHANGE (singlePred)");
+                if (GraalOptions.TraceLIRGeneratorLevel >= 3) {
+                    TTY.println(fs.toString());
+                }
+            }
+            lastState = fs;
+        }
+
+        for (Node instr : block.getInstructions()) {
+            if (GraalOptions.TraceLIRGeneratorLevel >= 3) {
+                TTY.println("LIRGen for " + instr);
+            }
+            FrameState stateAfter = null;
+            if (instr instanceof StateSplit) {
+                stateAfter = ((StateSplit) instr).stateAfter();
+            }
+            if (instr != instr.graph().start()) {
+                walkState(instr, stateAfter);
+                doRoot((Value) instr);
+            }
+            if (stateAfter != null) {
+                lastState = stateAfter;
+                if (GraalOptions.TraceLIRGeneratorLevel >= 2) {
+                    TTY.println("STATE CHANGE");
+                    if (GraalOptions.TraceLIRGeneratorLevel >= 3) {
+                        TTY.println(stateAfter.toString());
+                    }
+                }
+            }
+        }
+        if (block.blockSuccessors().size() >= 1 && !block.endsWithJump()) {
+            NodeArray successors = block.lastInstruction().successors();
+            assert successors.size() >= 1 : "should have at least one successor : " + block.lastInstruction();
+            block.lir().jump(getLIRBlock((FixedNode) successors.get(0)));
+        }
+
+        if (GraalOptions.TraceLIRGeneratorLevel >= 1) {
+            TTY.println("END Generating LIR for block B" + block.blockID());
+        }
+
+        block.setLastState(lastState);
+        this.currentBlock = null;
+        blockDoEpilog();
+    }
+
+    @Override
+    public void visitMerge(Merge x) {
+        if (x.next() instanceof LoopBegin) {
+            moveToPhi((LoopBegin) x.next(), x);
+        }
+    }
+
+    @Override
+    public void visitArrayLength(ArrayLength x) {
+        emitArrayLength(x);
+    }
+
+    public CiValue emitArrayLength(ArrayLength x) {
+        XirArgument array = toXirArgument(x.array());
+        XirSnippet snippet = xir.genArrayLength(site(x), array);
+        emitXir(snippet, x, stateFor(x), null, true);
+        return x.operand();
+    }
+
+    private FrameState setOperandsForLocals() {
+        CiCallingConvention args = compilation.frameMap().incomingArguments();
+        int bci = 0;
+        if (Modifier.isSynchronized(compilation.method.accessFlags())) {
+            bci = FixedNodeWithNext.SYNCHRONIZATION_ENTRY_BCI;
+        }
+
+        boolean withReceiver = !Modifier.isStatic(compilation.method.accessFlags());
+        CiKind[] arguments = Util.signatureToKinds(compilation.method.signature(), withReceiver ? CiKind.Object : null);
+        int[] argumentSlots = new int[arguments.length];
+        int slot = 0;
+        for (int arg = 0; arg < arguments.length; arg++) {
+            argumentSlots[arg] = slot;
+            slot += arguments[arg].sizeInSlots();
+        }
+
+        FrameState fs = new FrameState(compilation.method, bci, compilation.method.maxLocals(), 0, 0, false, compilation.graph);
+        for (Node node : compilation.graph.start().usages()) {
+            if (node instanceof Local) {
+                Local local = (Local) node;
+                int i = local.index();
+                fs.storeLocal(argumentSlots[i], local);
+
+                CiValue src = args.locations[i];
+                assert src.isLegal() : "check";
+
+                CiVariable dest = newVariable(src.kind.stackKind());
+                lir.move(src, dest, src.kind);
+
+                assert src.kind.stackKind() == local.kind.stackKind() : "local type check failed";
+                setResult(local, dest);
+            }
+        }
+        assert checkOperands(fs);
+        return fs;
+    }
+
+    private boolean checkOperands(FrameState fs) {
+        boolean withReceiver = !Modifier.isStatic(compilation.method.accessFlags());
+        CiKind[] arguments = Util.signatureToKinds(compilation.method.signature(), withReceiver ? CiKind.Object : null);
+        int slot = 0;
+        for (CiKind kind : arguments) {
+            assert fs.localAt(slot) != null : "slot: " + slot;
+            slot += kind.sizeInSlots();
+        }
+        return true;
+    }
+
+    @Override
+    public void visitCheckCast(CheckCast x) {
+        XirArgument obj = toXirArgument(x.object());
+        XirSnippet snippet = xir.genCheckCast(site(x), obj, toXirArgument(x.targetClassInstruction()), x.targetClass());
+        emitXir(snippet, x, stateFor(x), null, true);
+    }
+
+    @Override
+    public void visitMonitorEnter(MonitorEnter x) {
+        XirArgument obj = toXirArgument(x.object());
+        XirArgument lockAddress = toXirArgument(x.lockAddress());
+        XirSnippet snippet = xir.genMonitorEnter(site(x), obj, lockAddress);
+        emitXir(snippet, x, stateFor(x), stateFor(x, x.stateAfter()), null, true, null);
+    }
+
+    @Override
+    public void visitMonitorExit(MonitorExit x) {
+        XirArgument obj = toXirArgument(x.object());
+        XirArgument lockAddress = toXirArgument(x.lockAddress());
+        XirSnippet snippet = xir.genMonitorExit(site(x), obj, lockAddress);
+        emitXir(snippet, x, stateFor(x), null, true);
+    }
+
+    @Override
+    public void visitStoreIndexed(StoreIndexed x) {
+        XirArgument array = toXirArgument(x.array());
+        XirArgument length = x.length() == null ? null : toXirArgument(x.length());
+        XirArgument index = toXirArgument(x.index());
+        XirArgument value = toXirArgument(x.value());
+        XirSnippet snippet = xir.genArrayStore(site(x), array, index, length, value, x.elementKind(), null);
+        emitXir(snippet, x, stateFor(x), null, true);
+    }
+
+    @Override
+    public void visitNewInstance(NewInstance x) {
+        XirSnippet snippet = xir.genNewInstance(site(x), x.instanceClass());
+        emitXir(snippet, x, stateFor(x), null, true);
+    }
+
+    @Override
+    public void visitNewTypeArray(NewTypeArray x) {
+        XirArgument length = toXirArgument(x.length());
+        XirSnippet snippet = xir.genNewArray(site(x), length, x.elementKind(), null, null);
+        emitXir(snippet, x, stateFor(x), null, true);
+    }
+
+    @Override
+    public void visitNewObjectArray(NewObjectArray x) {
+        XirArgument length = toXirArgument(x.length());
+        XirSnippet snippet = xir.genNewArray(site(x), length, CiKind.Object, x.elementType(), x.exactType());
+        emitXir(snippet, x, stateFor(x), null, true);
+    }
+
+    @Override
+    public void visitNewMultiArray(NewMultiArray x) {
+        XirArgument[] dims = new XirArgument[x.dimensionCount()];
+
+        for (int i = 0; i < dims.length; i++) {
+            dims[i] = toXirArgument(x.dimension(i));
+        }
+
+        XirSnippet snippet = xir.genNewMultiArray(site(x), dims, x.elementType);
+        emitXir(snippet, x, stateFor(x), null, true);
+    }
+
+
+    @Override
+    public void visitGuardNode(GuardNode x) {
+        emitGuardComp(x.node());
+    }
+
+
+    @Override
+    public void visitConstant(Constant x) {
+        if (!canInlineAsConstant(x)) {
+            CiValue res = x.operand();
+            if (!(res.isLegal())) {
+                res = x.asConstant();
+            }
+            if (res.isConstant()) {
+                CiVariable reg = createResultVariable(x);
+                lir.move(res, reg);
+            } else {
+                setResult(x, (CiVariable) res);
+            }
+        }
+    }
+
+    @Override
+    public void visitExceptionObject(ExceptionObject x) {
+        XirSnippet snippet = xir.genExceptionObject(site(x));
+        emitXir(snippet, x, null, null, true);
+//        lastState = lastState.duplicateWithException(lastState.bci, x);
+//        if (GraalOptions.TraceLIRGeneratorLevel >= 2) {
+//            TTY.println("STATE CHANGE (visitExceptionObject)");
+//            if (GraalOptions.TraceLIRGeneratorLevel >= 3) {
+//                TTY.println(lastState.toString());
+//            }
+//        }
+    }
+
+    @Override
+    public void visitAnchor(Anchor x) {
+        setNoResult(x);
+    }
+
+    @Override
+    public void visitIf(If x) {
+        assert x.defaultSuccessor() == x.falseSuccessor() : "wrong destination";
+        emitBooleanBranch(x.compare(), getLIRBlock(x.trueSuccessor()),  getLIRBlock(x.falseSuccessor()), null);
+    }
+
+    public void emitBranch(BooleanNode n, Condition cond, LIRBlock trueSuccessor, LIRBlock falseSucc) {
+        if (n instanceof Compare) {
+            Compare compare = (Compare) n;
+            if (compare.x().kind.isFloat() || compare.x().kind.isDouble()) {
+                LIRBlock unorderedSuccBlock = falseSucc;
+                if (compare.unorderedIsTrue()) {
+                    unorderedSuccBlock = trueSuccessor;
+                }
+                lir.branch(cond, trueSuccessor, unorderedSuccBlock);
+                return;
+            }
+        }
+        lir.branch(cond, trueSuccessor);
+    }
+
+    public void emitBooleanBranch(Node node, LIRBlock trueSuccessor, LIRBlock falseSuccessor, LIRDebugInfo info) {
+        if (node instanceof NegateBooleanNode) {
+            emitBooleanBranch(((NegateBooleanNode) node).value(), falseSuccessor, trueSuccessor, info);
+        } else if (node instanceof Compare) {
+            emitCompare((Compare) node, trueSuccessor, falseSuccessor);
+        } else if (node instanceof InstanceOf) {
+            emitInstanceOf((TypeCheck) node, trueSuccessor, falseSuccessor, info);
+        } else if (node instanceof Constant) {
+            emitConstantBranch(((Constant) node).asConstant().asBoolean(), trueSuccessor, falseSuccessor, info);
+        } else {
+            throw Util.unimplemented(node.toString());
+        }
+    }
+
+    private void emitInstanceOf(TypeCheck x, LIRBlock trueSuccessor, LIRBlock falseSuccessor, LIRDebugInfo info) {
+        XirArgument obj = toXirArgument(x.object());
+        XirSnippet snippet = xir.genInstanceOf(site(x), obj, toXirArgument(x.targetClassInstruction()), x.targetClass());
+        emitXir(snippet, x, info, null, false);
+        LIRXirInstruction instr = (LIRXirInstruction) lir.instructionsList().get(lir.instructionsList().size() - 1);
+        instr.setTrueSuccessor(trueSuccessor);
+        instr.setFalseSuccessor(falseSuccessor);
+    }
+
+
+    public void emitConstantBranch(boolean value, LIRBlock trueSuccessorBlock, LIRBlock falseSuccessorBlock, LIRDebugInfo info) {
+        if (value) {
+            emitConstantBranch(trueSuccessorBlock, info);
+        } else {
+            emitConstantBranch(falseSuccessorBlock, info);
+        }
+    }
+
+    private void emitConstantBranch(LIRBlock block, LIRDebugInfo info) {
+        if (block != null) {
+            lir.jump(block);
+        }
+    }
+
+    public void emitCompare(Compare compare, LIRBlock trueSuccessorBlock, LIRBlock falseSuccessorBlock) {
+        CiKind kind = compare.x().kind;
+
+        Condition cond = compare.condition();
+        boolean unorderedIsTrue = compare.unorderedIsTrue();
+
+        if (trueSuccessorBlock == null) {
+            cond = cond.negate();
+            unorderedIsTrue = !unorderedIsTrue;
+            trueSuccessorBlock = falseSuccessorBlock;
+            falseSuccessorBlock = null;
+        }
+
+        LIRItem xitem = new LIRItem(compare.x(), this);
+        LIRItem yitem = new LIRItem(compare.y(), this);
+        LIRItem xin = xitem;
+        LIRItem yin = yitem;
+
+        if (kind.isLong()) {
+            // for longs, only conditions "eql", "neq", "lss", "geq" are valid;
+            // mirror for other conditions
+            if (cond == Condition.GT || cond == Condition.LE) {
+                cond = cond.mirror();
+                xin = yitem;
+                yin = xitem;
+            }
+            xin.setDestroysRegister();
+        }
+        xin.loadItem();
+        if (kind.isLong() && yin.result().isConstant() && yin.instruction.asConstant().asLong() == 0 && (cond == Condition.EQ || cond == Condition.NE)) {
+            // dont load item
+        } else if (kind.isLong() || kind.isFloat() || kind.isDouble()) {
+            // longs cannot handle constants at right side
+            yin.loadItem();
+        }
+
+        CiValue left = xin.result();
+        CiValue right = yin.result();
+        lir.cmp(cond, left, right);
+
+        if (compare.x().kind.isFloat() || compare.x().kind.isDouble()) {
+            LIRBlock unorderedSuccBlock = falseSuccessorBlock;
+            if (unorderedIsTrue) {
+                unorderedSuccBlock = trueSuccessorBlock;
+            }
+            lir.branch(cond, trueSuccessorBlock, unorderedSuccBlock);
+        } else {
+            lir.branch(cond, trueSuccessorBlock);
+        }
+
+        if (falseSuccessorBlock != null) {
+            lir.jump(falseSuccessorBlock);
+        }
+    }
+
+    @Override
+    public void visitIfOp(Conditional i) {
+        Value x = i.x();
+        Value y = i.y();
+        CiKind xtype = x.kind;
+        CiKind ttype = i.trueValue().kind;
+        assert xtype.isInt() || xtype.isObject() : "cannot handle others";
+        assert ttype.isInt() || ttype.isObject() || ttype.isLong() || ttype.isWord() : "cannot handle others";
+        assert ttype.equals(i.falseValue().kind) : "cannot handle others";
+
+        CiValue left = load(x);
+        CiValue right = null;
+        if (!canInlineAsConstant(y)) {
+            right = load(y);
+        } else {
+            right = makeOperand(y);
+        }
+
+        CiValue tVal = makeOperand(i.trueValue());
+        CiValue fVal = makeOperand(i.falseValue());
+        CiValue reg = createResultVariable(i);
+
+        lir.cmp(i.condition(), left, right);
+        lir.cmove(i.condition(), tVal, fVal, reg);
+    }
+
+    protected FrameState stateBeforeInvokeReturn(Invoke invoke) {
+        return invoke.stateAfter().duplicateModified(invoke.bci, invoke.stateAfter().rethrowException(), invoke.kind);
+    }
+
+    protected FrameState stateBeforeInvokeWithArguments(Invoke invoke) {
+        return invoke.stateAfter().duplicateModified(invoke.bci, invoke.stateAfter().rethrowException(), invoke.kind, invoke.arguments().toArray(new Value[0]));
+    }
+
+    @Override
+    public void visitInvoke(Invoke x) {
+        RiMethod target = x.target();
+        LIRDebugInfo info = stateFor(x, stateBeforeInvokeWithArguments(x));
+        LIRDebugInfo info2 = stateFor(x, stateBeforeInvokeReturn(x));
+        if (x.exceptionEdge() != null) {
+            info2.setExceptionEdge(getLIRBlock(x.exceptionEdge()));
+        }
+
+        XirSnippet snippet = null;
+
+        int opcode = x.opcode();
+        XirArgument receiver;
+        switch (opcode) {
+            case INVOKESTATIC:
+                snippet = xir.genInvokeStatic(site(x), target);
+                break;
+            case INVOKESPECIAL:
+                receiver = toXirArgument(x.receiver());
+                snippet = xir.genInvokeSpecial(site(x), receiver, target);
+                break;
+            case INVOKEVIRTUAL:
+                receiver = toXirArgument(x.receiver());
+                snippet = xir.genInvokeVirtual(site(x), receiver, target);
+                break;
+            case INVOKEINTERFACE:
+                receiver = toXirArgument(x.receiver());
+                snippet = xir.genInvokeInterface(site(x), receiver, target);
+                break;
+        }
+
+        CiValue destinationAddress = null;
+        // emitting the template earlier can ease pressure on register allocation, but the argument loading can destroy an
+        // implicit calling convention between the XirSnippet and the call.
+        if (!GraalOptions.InvokeSnippetAfterArguments) {
+            destinationAddress = emitXir(snippet, x, info.copy(), x.target(), false);
+        }
+
+        CiValue resultOperand = resultOperandFor(x.kind);
+        CiCallingConvention cc = compilation.frameMap().getCallingConvention(x.signature(), JavaCall);
+        List<CiValue> pointerSlots = new ArrayList<CiValue>(2);
+        List<CiValue> argList = visitInvokeArguments(cc, x, pointerSlots);
+
+        if (GraalOptions.InvokeSnippetAfterArguments) {
+            destinationAddress = emitXir(snippet, x, info.copy(), null, x.target(), false, pointerSlots);
+        }
+
+        // emit direct or indirect call to the destination address
+        if (destinationAddress instanceof CiConstant) {
+            // Direct call
+            assert ((CiConstant) destinationAddress).isDefaultValue() : "destination address should be zero";
+            lir.callDirect(target, resultOperand, argList, info2, snippet.marks, pointerSlots);
+        } else {
+            // Indirect call
+            argList.add(destinationAddress);
+            lir.callIndirect(target, resultOperand, argList, info2, snippet.marks, pointerSlots);
+        }
+
+        if (resultOperand.isLegal()) {
+            CiValue result = createResultVariable(x);
+            lir.move(resultOperand, result);
+        }
+    }
+
+    @Override
+    public void visitMonitorAddress(MonitorAddress x) {
+        CiValue result = createResultVariable(x);
+        lir.monitorAddress(x.monitorIndex(), result);
+    }
+
+    /**
+     * For note on volatile fields, see {@link #visitStoreField(StoreField)}.
+     */
+    @Override
+    public void visitLoadField(LoadField x) {
+        RiField field = x.field();
+        LIRDebugInfo info = stateFor(x);
+        XirArgument receiver = toXirArgument(x.object());
+        XirSnippet snippet = x.isStatic() ? xir.genGetStatic(site(x), receiver, field) : xir.genGetField(site(x), receiver, field);
+        emitXir(snippet, x, info, null, true);
+
+        if (x.isVolatile()) {
+            vma.postVolatileRead();
+        }
+    }
+
+    @Override
+    public void visitLoadIndexed(LoadIndexed x) {
+        XirArgument array = toXirArgument(x.array());
+        XirArgument index = toXirArgument(x.index());
+        XirArgument length = toXirArgument(x.length());
+        XirSnippet snippet = xir.genArrayLoad(site(x), array, index, length, x.elementKind(), null);
+        emitXir(snippet, x, stateFor(x), null, true);
+    }
+
+    protected GlobalStub stubFor(CiRuntimeCall runtimeCall) {
+        GlobalStub stub = compilation.compiler.lookupGlobalStub(runtimeCall);
+        compilation.frameMap().usesGlobalStub(stub);
+        return stub;
+    }
+
+    protected GlobalStub stubFor(GlobalStub.Id globalStub) {
+        GlobalStub stub = compilation.compiler.lookupGlobalStub(globalStub);
+        compilation.frameMap().usesGlobalStub(stub);
+        return stub;
+    }
+
+    protected GlobalStub stubFor(XirTemplate template) {
+        GlobalStub stub = compilation.compiler.lookupGlobalStub(template);
+        compilation.frameMap().usesGlobalStub(stub);
+        return stub;
+    }
+
+    @Override
+    public void visitLocal(Local x) {
+        if (x.operand().isIllegal()) {
+            createResultVariable(x);
+        }
+    }
+
+    @Override
+    public void visitLookupSwitch(LookupSwitch x) {
+        CiValue tag = load(x.value());
+        setNoResult(x);
+
+        if (x.numberOfCases() == 0 || x.numberOfCases() < GraalOptions.SequentialSwitchLimit) {
+            int len = x.numberOfCases();
+            for (int i = 0; i < len; i++) {
+                lir.cmp(Condition.EQ, tag, x.keyAt(i));
+                lir.branch(Condition.EQ, getLIRBlock(x.blockSuccessor(i)));
+            }
+            lir.jump(getLIRBlock(x.defaultSuccessor()));
+        } else {
+            visitSwitchRanges(createLookupRanges(x), tag, getLIRBlock(x.defaultSuccessor()));
+        }
+    }
+
+    protected LIRBlock getLIRBlock(FixedNode b) {
+        if (b == null) {
+            return null;
+        }
+        LIRBlock result = ir.valueToBlock.get(b);
+        if (result == null) {
+            TTY.println("instruction without lir block: " + b);
+        }
+        return result;
+    }
+
+    @Override
+    public void visitFixedGuard(FixedGuard fixedGuard) {
+        for (Node n : fixedGuard.inputs()) {
+            if (n != null) {
+                emitGuardComp((BooleanNode) n);
+    }
+        }
+    }
+
+    public void emitGuardComp(BooleanNode comp) {
+        if (comp instanceof IsNonNull) {
+            IsNonNull x = (IsNonNull) comp;
+            CiValue value = load(x.object());
+            LIRDebugInfo info = stateFor(x);
+            lir.nullCheck(value, info);
+        } else if (comp instanceof IsType) {
+            IsType x = (IsType) comp;
+            load(x.object());
+            LIRDebugInfo info = stateFor(x);
+            XirArgument clazz = toXirArgument(x.type().getEncoding(Representation.ObjectHub));
+            XirSnippet typeCheck = xir.genTypeCheck(site(x), toXirArgument(x.object()), clazz, x.type());
+            emitXir(typeCheck, x, info, compilation.method, false);
+        } else {
+            if (comp instanceof Constant && comp.asConstant().asBoolean()) {
+                // Nothing to emit.
+            } else {
+                DeoptimizationStub stub = createDeoptStub();
+                emitBooleanBranch(comp, null, new LIRBlock(stub.label, stub.info), stub.info);
+            }
+        }
+    }
+
+    private DeoptimizationStub createDeoptStub() {
+        if (deoptimizationStubs == null) {
+            deoptimizationStubs = new ArrayList<DeoptimizationStub>();
+        }
+
+        FrameState state = lastState;
+        assert state != null : "deoptimize instruction always needs a state";
+        DeoptimizationStub stub = new DeoptimizationStub(DeoptAction.InvalidateReprofile, state);
+        deoptimizationStubs.add(stub);
+        return stub;
+    }
+
+    public void deoptimizeOn(Condition cond) {
+        DeoptimizationStub stub = createDeoptStub();
+        lir.branch(cond, stub.label, stub.info);
+    }
+
+
+    @Override
+    public void visitPhi(Phi i) {
+        Util.shouldNotReachHere();
+    }
+
+    @Override
+    public void visitReturn(Return x) {
+        if (x.kind.isVoid()) {
+            XirSnippet epilogue = xir.genEpilogue(site(x), compilation.method);
+            if (epilogue != null) {
+                emitXir(epilogue, x, null, compilation.method, false);
+                lir.returnOp(IllegalValue);
+            }
+        } else {
+            CiValue operand = resultOperandFor(x.kind);
+            CiValue result = force(x.result(), operand);
+            XirSnippet epilogue = xir.genEpilogue(site(x), compilation.method);
+            if (epilogue != null) {
+                emitXir(epilogue, x, null, compilation.method, false);
+                lir.returnOp(result);
+            }
+        }
+        setNoResult(x);
+    }
+
+    protected XirArgument toXirArgument(CiValue v) {
+        if (v == null) {
+            return null;
+        }
+
+        return XirArgument.forInternalObject(v);
+    }
+
+    protected XirArgument toXirArgument(Value i) {
+        if (i == null) {
+            return null;
+        }
+
+        return XirArgument.forInternalObject(new LIRItem(i, this));
+    }
+
+    private CiValue allocateOperand(XirSnippet snippet, XirOperand op) {
+        if (op instanceof XirParameter)  {
+            XirParameter param = (XirParameter) op;
+            return allocateOperand(snippet.arguments[param.parameterIndex], op, param.canBeConstant);
+        } else if (op instanceof XirRegister) {
+            XirRegister reg = (XirRegister) op;
+            return reg.register;
+        } else if (op instanceof XirTemp) {
+            return newVariable(op.kind);
+        } else {
+            Util.shouldNotReachHere();
+            return null;
+        }
+    }
+
+    private CiValue allocateOperand(XirArgument arg, XirOperand var, boolean canBeConstant) {
+        if (arg.constant != null) {
+            return arg.constant;
+        } else {
+            assert arg.object != null;
+            if (arg.object instanceof CiValue) {
+                return (CiValue) arg.object;
+            }
+            assert arg.object instanceof LIRItem;
+            LIRItem item = (LIRItem) arg.object;
+            if (canBeConstant) {
+                return item.instruction.operand();
+            } else {
+                CiKind kind = var.kind;
+                if (kind == CiKind.Byte || kind == CiKind.Boolean) {
+                    item.loadByteItem();
+                } else {
+                    item.loadItem();
+                }
+                return item.result();
+            }
+        }
+    }
+
+    protected CiValue emitXir(XirSnippet snippet, Value x, LIRDebugInfo info, RiMethod method, boolean setInstructionResult) {
+        return emitXir(snippet, x, info, null, method, setInstructionResult, null);
+    }
+
+    protected CiValue emitXir(XirSnippet snippet, Value instruction, LIRDebugInfo info, LIRDebugInfo infoAfter, RiMethod method, boolean setInstructionResult, List<CiValue> pointerSlots) {
+        if (GraalOptions.PrintXirTemplates) {
+            TTY.println("Emit XIR template " + snippet.template.name);
+        }
+
+        final CiValue[] operands = new CiValue[snippet.template.variableCount];
+
+        compilation.frameMap().reserveOutgoing(snippet.template.outgoingStackSize);
+
+        XirOperand resultOperand = snippet.template.resultOperand;
+
+        if (snippet.template.allocateResultOperand) {
+            CiValue outputOperand = IllegalValue;
+            // This snippet has a result that must be separately allocated
+            // Otherwise it is assumed that the result is part of the inputs
+            if (resultOperand.kind != CiKind.Void && resultOperand.kind != CiKind.Illegal) {
+                if (setInstructionResult) {
+                    outputOperand = newVariable(instruction.kind);
+                } else {
+                    outputOperand = newVariable(resultOperand.kind);
+                }
+                assert operands[resultOperand.index] == null;
+            }
+            operands[resultOperand.index] = outputOperand;
+            if (GraalOptions.PrintXirTemplates) {
+                TTY.println("Output operand: " + outputOperand);
+            }
+        }
+
+        for (XirTemp t : snippet.template.temps) {
+            if (t instanceof XirRegister) {
+                XirRegister reg = (XirRegister) t;
+                if (!t.reserve) {
+                    operands[t.index] = reg.register;
+                }
+            }
+        }
+
+        for (XirTemplate calleeTemplate : snippet.template.calleeTemplates) {
+            // TODO Save these for use in X86LIRAssembler
+            stubFor(calleeTemplate);
+        }
+
+        for (XirConstant c : snippet.template.constants) {
+            assert operands[c.index] == null;
+            operands[c.index] = c.value;
+        }
+
+        XirOperand[] inputOperands = snippet.template.inputOperands;
+        XirOperand[] inputTempOperands = snippet.template.inputTempOperands;
+        XirOperand[] tempOperands = snippet.template.tempOperands;
+
+        CiValue[] operandArray = new CiValue[inputOperands.length + inputTempOperands.length + tempOperands.length];
+        int[] operandIndicesArray = new int[inputOperands.length + inputTempOperands.length + tempOperands.length];
+        for (int i = 0; i < inputOperands.length; i++) {
+            XirOperand x = inputOperands[i];
+            CiValue op = allocateOperand(snippet, x);
+            operands[x.index] = op;
+            operandArray[i] = op;
+            operandIndicesArray[i] = x.index;
+            if (GraalOptions.PrintXirTemplates) {
+                TTY.println("Input operand: " + x);
+            }
+        }
+
+        for (int i = 0; i < inputTempOperands.length; i++) {
+            XirOperand x = inputTempOperands[i];
+            CiValue op = allocateOperand(snippet, x);
+            CiValue newOp = newVariable(op.kind);
+            lir.move(op, newOp);
+            operands[x.index] = newOp;
+            operandArray[i + inputOperands.length] = newOp;
+            operandIndicesArray[i + inputOperands.length] = x.index;
+            if (GraalOptions.PrintXirTemplates) {
+                TTY.println("InputTemp operand: " + x);
+            }
+        }
+
+        for (int i = 0; i < tempOperands.length; i++) {
+            XirOperand x = tempOperands[i];
+            CiValue op = allocateOperand(snippet, x);
+            operands[x.index] = op;
+            operandArray[i + inputOperands.length + inputTempOperands.length] = op;
+            operandIndicesArray[i + inputOperands.length + inputTempOperands.length] = x.index;
+            if (GraalOptions.PrintXirTemplates) {
+                TTY.println("Temp operand: " + x);
+            }
+        }
+
+        for (CiValue operand : operands) {
+            assert operand != null;
+        }
+
+        CiValue allocatedResultOperand = operands[resultOperand.index];
+        if (!allocatedResultOperand.isVariableOrRegister()) {
+            allocatedResultOperand = IllegalValue;
+        }
+
+        if (setInstructionResult && allocatedResultOperand.isLegal()) {
+            if (instruction.operand().isIllegal()) {
+                setResult(instruction, (CiVariable) allocatedResultOperand);
+            } else {
+                assert instruction.operand() == allocatedResultOperand;
+            }
+        }
+
+
+        XirInstruction[] slowPath = snippet.template.slowPath;
+        if (!operands[resultOperand.index].isConstant() || snippet.template.fastPath.length != 0 || (slowPath != null && slowPath.length > 0)) {
+            // XIR instruction is only needed when the operand is not a constant!
+            lir.xir(snippet, operands, allocatedResultOperand, inputTempOperands.length, tempOperands.length,
+                    operandArray, operandIndicesArray,
+                    (operands[resultOperand.index] == IllegalValue) ? -1 : resultOperand.index,
+                    info, infoAfter, method, pointerSlots);
+        }
+
+        return operands[resultOperand.index];
+    }
+
+    @Override
+    public void visitStoreField(StoreField x) {
+        RiField field = x.field();
+        LIRDebugInfo info = stateFor(x);
+
+        if (x.isVolatile()) {
+            vma.preVolatileWrite();
+        }
+
+        XirArgument receiver = toXirArgument(x.object());
+        XirArgument value = toXirArgument(x.value());
+        XirSnippet snippet = x.isStatic() ? xir.genPutStatic(site(x), receiver, field, value) : xir.genPutField(site(x), receiver, field, value);
+        emitXir(snippet, x, info, null, true);
+
+        if (x.isVolatile()) {
+            vma.postVolatileWrite();
+        }
+    }
+
+    @Override
+    public void visitTableSwitch(TableSwitch x) {
+
+        LIRItem value = new LIRItem(x.value(), this);
+        // Making a copy of the switch value is necessary when generating a jump table
+        value.setDestroysRegister();
+        value.loadItem();
+
+        CiValue tag = value.result();
+        setNoResult(x);
+
+        // TODO: tune the defaults for the controls used to determine what kind of translation to use
+        if (x.numberOfCases() == 0 || x.numberOfCases() <= GraalOptions.SequentialSwitchLimit) {
+            int loKey = x.lowKey();
+            int len = x.numberOfCases();
+            for (int i = 0; i < len; i++) {
+                lir.cmp(Condition.EQ, tag, i + loKey);
+                lir.branch(Condition.EQ, getLIRBlock(x.blockSuccessor(i)));
+            }
+            lir.jump(getLIRBlock(x.defaultSuccessor()));
+        } else {
+            SwitchRange[] switchRanges = createLookupRanges(x);
+            int rangeDensity = x.numberOfCases() / switchRanges.length;
+            if (rangeDensity >= GraalOptions.RangeTestsSwitchDensity) {
+                visitSwitchRanges(switchRanges, tag, getLIRBlock(x.defaultSuccessor()));
+            } else {
+                LIRBlock[] targets = new LIRBlock[x.numberOfCases()];
+                for (int i = 0; i < x.numberOfCases(); ++i) {
+                    targets[i] = getLIRBlock(x.blockSuccessor(i));
+                }
+                lir.tableswitch(tag, x.lowKey(), getLIRBlock(x.defaultSuccessor()), targets);
+            }
+        }
+    }
+
+    @Override
+    public void visitDeoptimize(Deoptimize deoptimize) {
+        assert lastState != null : "deoptimize always needs a state";
+        assert lastState.bci != FixedNodeWithNext.SYNCHRONIZATION_ENTRY_BCI : "bci must not be -1 for deopt framestate";
+        DeoptimizationStub stub = new DeoptimizationStub(deoptimize.action(), lastState);
+        addDeoptimizationStub(stub);
+        lir.branch(Condition.TRUE, stub.label, stub.info);
+    }
+
+    private void blockDoEpilog() {
+        if (GraalOptions.PrintIRWithLIR) {
+            TTY.println();
+        }
+
+        // clear out variables for local constants
+        constants.clear();
+        variablesForConstants.clear();
+    }
+
+    private void blockDoProlog(LIRBlock block) {
+        if (GraalOptions.PrintIRWithLIR) {
+            TTY.print(block.toString());
+        }
+        // set up the list of LIR instructions
+        assert block.lir() == null : "LIR list already computed for this block";
+        lir = new LIRList(this);
+        block.setLir(lir);
+
+        lir.branchDestination(block.label());
+    }
+
+    /**
+     * Copies a given value into an operand that is forced to be a stack location.
+     *
+     * @param value a value to be forced onto the stack
+     * @param kind the kind of new operand
+     * @param mustStayOnStack specifies if the new operand must never be allocated to a register
+     * @return the operand that is guaranteed to be a stack location when it is
+     *         initially defined a by move from {@code value}
+     */
+    public CiValue forceToSpill(CiValue value, CiKind kind, boolean mustStayOnStack) {
+        assert value.isLegal() : "value should not be illegal";
+        assert kind.jvmSlots == value.kind.jvmSlots : "size mismatch";
+        if (!value.isVariableOrRegister()) {
+            // force into a variable that must start in memory
+            CiValue operand = operands.newVariable(value.kind, mustStayOnStack ? VariableFlag.MustStayInMemory : VariableFlag.MustStartInMemory);
+            lir.move(value, operand);
+            return operand;
+        }
+
+        // create a spill location
+        CiValue operand = operands.newVariable(kind, mustStayOnStack ? VariableFlag.MustStayInMemory : VariableFlag.MustStartInMemory);
+        // move from register to spill
+        lir.move(value, operand);
+        return operand;
+    }
+
+    private CiVariable loadConstant(Constant x) {
+        return loadConstant(x.asConstant(), x.kind);
+    }
+
+    protected CiVariable loadConstant(CiConstant c, CiKind kind) {
+        // XXX: linear search might be kind of slow for big basic blocks
+        int index = constants.indexOf(c);
+        if (index != -1) {
+            GraalMetrics.LoadConstantIterations += index;
+            return variablesForConstants.get(index);
+        }
+        GraalMetrics.LoadConstantIterations += constants.size();
+
+        CiVariable result = newVariable(kind);
+        lir.move(c, result);
+        constants.add(c);
+        variablesForConstants.add(result);
+        return result;
+    }
+
+    /**
+     * Allocates a variable operand to hold the result of a given instruction.
+     * This can only be performed once for any given instruction.
+     *
+     * @param x an instruction that produces a result
+     * @return the variable assigned to hold the result produced by {@code x}
+     */
+    public CiVariable createResultVariable(Value x) {
+        CiVariable operand = newVariable(x.kind);
+        setResult(x, operand);
+        return operand;
+    }
+
+    @Override
+    public void visitRegisterFinalizer(RegisterFinalizer x) {
+        CiValue receiver = load(x.object());
+        LIRDebugInfo info = stateFor(x);
+        callRuntime(CiRuntimeCall.RegisterFinalizer, info, receiver);
+        setNoResult(x);
+    }
+
+    private void visitSwitchRanges(SwitchRange[] x, CiValue value, LIRBlock defaultSux) {
+        for (int i = 0; i < x.length; i++) {
+            SwitchRange oneRange = x[i];
+            int lowKey = oneRange.lowKey;
+            int highKey = oneRange.highKey;
+            LIRBlock dest = oneRange.sux;
+            if (lowKey == highKey) {
+                lir.cmp(Condition.EQ, value, lowKey);
+                lir.branch(Condition.EQ, dest);
+            } else if (highKey - lowKey == 1) {
+                lir.cmp(Condition.EQ, value, lowKey);
+                lir.branch(Condition.EQ, dest);
+                lir.cmp(Condition.EQ, value, highKey);
+                lir.branch(Condition.EQ, dest);
+            } else {
+                Label l = new Label();
+                lir.cmp(Condition.LT, value, lowKey);
+                lir.branch(Condition.LT, l);
+                lir.cmp(Condition.LE, value, highKey);
+                lir.branch(Condition.LE, dest);
+                lir.branchDestination(l);
+            }
+        }
+        lir.jump(defaultSux);
+    }
+
+    protected void arithmeticOpFpu(int code, CiValue result, CiValue left, CiValue right, CiValue tmp) {
+        CiValue leftOp = left;
+
+        if (isTwoOperand && leftOp != result) {
+            assert right != result : "malformed";
+            lir.move(leftOp, result);
+            leftOp = result;
+        }
+
+        switch (code) {
+            case DADD:
+            case FADD:
+                lir.add(leftOp, right, result);
+                break;
+            case FMUL:
+            case DMUL:
+                lir.mul(leftOp, right, result);
+                break;
+            case DSUB:
+            case FSUB:
+                lir.sub(leftOp, right, result);
+                break;
+            case FDIV:
+            case DDIV:
+                lir.div(leftOp, right, result, null);
+                break;
+            default:
+                Util.shouldNotReachHere();
+        }
+    }
+
+    public void integerAdd(Value result, Value left, Value right) {
+        arithmeticOpInt(Bytecodes.IADD, createResultVariable(result), load(left), load(right), CiValue.IllegalValue);
+    }
+
+    public void arithmeticOpInt(int code, CiValue result, CiValue left, CiValue right, CiValue tmp) {
+        CiValue leftOp = left;
+
+        if (isTwoOperand && leftOp != result) {
+            assert right != result : "malformed";
+            lir.move(leftOp, result);
+            leftOp = result;
+        }
+
+        switch (code) {
+            case IADD:
+                lir.add(leftOp, right, result);
+                break;
+            case IMUL:
+                boolean didStrengthReduce = false;
+                if (right.isConstant()) {
+                    CiConstant rightConstant = (CiConstant) right;
+                    int c = rightConstant.asInt();
+                    if (CiUtil.isPowerOf2(c)) {
+                        // do not need tmp here
+                        lir.shiftLeft(leftOp, CiUtil.log2(c), result);
+                        didStrengthReduce = true;
+                    } else {
+                        didStrengthReduce = strengthReduceMultiply(leftOp, c, result, tmp);
+                    }
+                }
+                // we couldn't strength reduce so just emit the multiply
+                if (!didStrengthReduce) {
+                    lir.mul(leftOp, right, result);
+                }
+                break;
+            case ISUB:
+                lir.sub(leftOp, right, result);
+                break;
+            default:
+                // idiv and irem are handled elsewhere
+                Util.shouldNotReachHere();
+        }
+    }
+
+    public void arithmeticOpLong(int code, CiValue result, CiValue left, CiValue right) {
+        CiValue leftOp = left;
+
+        if (isTwoOperand && leftOp != result) {
+            assert right != result : "malformed";
+            lir.move(leftOp, result);
+            leftOp = result;
+        }
+
+        switch (code) {
+            case LADD:
+                lir.add(leftOp, right, result);
+                break;
+            case LMUL:
+                lir.mul(leftOp, right, result);
+                break;
+            case LSUB:
+                lir.sub(leftOp, right, result);
+                break;
+            default:
+                // ldiv and lrem are handled elsewhere
+                Util.shouldNotReachHere();
+        }
+    }
+
+    protected final CiValue callRuntime(CiRuntimeCall runtimeCall, LIRDebugInfo info, CiValue... args) {
+        // get a result register
+        CiKind result = runtimeCall.resultKind;
+        CiKind[] arguments = runtimeCall.arguments;
+
+        CiValue physReg = result.isVoid() ? IllegalValue : resultOperandFor(result);
+
+        List<CiValue> argumentList;
+        if (arguments.length > 0) {
+            // move the arguments into the correct location
+            CiCallingConvention cc = compilation.frameMap().getCallingConvention(arguments, RuntimeCall);
+            assert cc.locations.length == args.length : "argument count mismatch";
+            for (int i = 0; i < args.length; i++) {
+                CiValue arg = args[i];
+                CiValue loc = cc.locations[i];
+                if (loc.isRegister()) {
+                    lir.move(arg, loc);
+                } else {
+                    assert loc.isStackSlot();
+                    CiStackSlot slot = (CiStackSlot) loc;
+                    if (slot.kind == CiKind.Long || slot.kind == CiKind.Double) {
+                        lir.unalignedMove(arg, slot);
+                    } else {
+                        lir.move(arg, slot);
+                    }
+                }
+            }
+            argumentList = Arrays.asList(cc.locations);
+        } else {
+            // no arguments
+            assert args == null || args.length == 0;
+            argumentList = Util.uncheckedCast(Collections.emptyList());
+        }
+
+        lir.callRuntime(runtimeCall, physReg, argumentList, info);
+
+        return physReg;
+    }
+
+    protected final CiVariable callRuntimeWithResult(CiRuntimeCall runtimeCall, LIRDebugInfo info, CiValue... args) {
+        CiVariable result = newVariable(runtimeCall.resultKind);
+        CiValue location = callRuntime(runtimeCall, info, args);
+        lir.move(location, result);
+        return result;
+    }
+
+    SwitchRange[] createLookupRanges(LookupSwitch x) {
+        // we expect the keys to be sorted by increasing value
+        List<SwitchRange> res = new ArrayList<SwitchRange>(x.numberOfCases());
+        int len = x.numberOfCases();
+        if (len > 0) {
+            LIRBlock defaultSux = getLIRBlock(x.defaultSuccessor());
+            int key = x.keyAt(0);
+            LIRBlock sux = getLIRBlock(x.blockSuccessor(0));
+            SwitchRange range = new SwitchRange(key, sux);
+            for (int i = 1; i < len; i++) {
+                int newKey = x.keyAt(i);
+                LIRBlock newSux = getLIRBlock(x.blockSuccessor(i));
+                if (key + 1 == newKey && sux == newSux) {
+                    // still in same range
+                    range.highKey = newKey;
+                } else {
+                    // skip tests which explicitly dispatch to the default
+                    if (range.sux != defaultSux) {
+                        res.add(range);
+                    }
+                    range = new SwitchRange(newKey, newSux);
+                }
+                key = newKey;
+                sux = newSux;
+            }
+            if (res.size() == 0 || res.get(res.size() - 1) != range) {
+                res.add(range);
+            }
+        }
+        return res.toArray(new SwitchRange[res.size()]);
+    }
+
+    SwitchRange[] createLookupRanges(TableSwitch x) {
+        // XXX: try to merge this with the code for LookupSwitch
+        List<SwitchRange> res = new ArrayList<SwitchRange>(x.numberOfCases());
+        int len = x.numberOfCases();
+        if (len > 0) {
+            LIRBlock sux = getLIRBlock(x.blockSuccessor(0));
+            int key = x.lowKey();
+            LIRBlock defaultSux = getLIRBlock(x.defaultSuccessor());
+            SwitchRange range = new SwitchRange(key, sux);
+            for (int i = 0; i < len; i++, key++) {
+                LIRBlock newSux = getLIRBlock(x.blockSuccessor(i));
+                if (sux == newSux) {
+                    // still in same range
+                    range.highKey = key;
+                } else {
+                    // skip tests which explicitly dispatch to the default
+                    if (sux != defaultSux) {
+                        res.add(range);
+                    }
+                    range = new SwitchRange(key, newSux);
+                }
+                sux = newSux;
+            }
+            if (res.size() == 0 || res.get(res.size() - 1) != range) {
+                res.add(range);
+            }
+        }
+        return res.toArray(new SwitchRange[res.size()]);
+    }
+
+    void doRoot(Value instr) {
+        if (GraalOptions.TraceLIRGeneratorLevel >= 2) {
+            TTY.println("Emitting LIR for instruction " + instr);
+        }
+        currentInstruction = instr;
+
+        if (GraalOptions.TraceLIRVisit) {
+            TTY.println("Visiting    " + instr);
+        }
+
+        LIRGeneratorOp op = instr.lookup(LIRGeneratorOp.class);
+        if (op != null) {
+            op.generate(instr, this);
+        }
+
+        if (GraalOptions.TraceLIRVisit) {
+            TTY.println("Operand for " + instr + " = " + instr.operand());
+        }
+    }
+
+    protected void logicOp(int code, CiValue resultOp, CiValue leftOp, CiValue rightOp) {
+        if (isTwoOperand && leftOp != resultOp) {
+            assert rightOp != resultOp : "malformed";
+            lir.move(leftOp, resultOp);
+            leftOp = resultOp;
+        }
+
+        switch (code) {
+            case IAND:
+            case LAND:
+                lir.logicalAnd(leftOp, rightOp, resultOp);
+                break;
+
+            case IOR:
+            case LOR:
+                lir.logicalOr(leftOp, rightOp, resultOp);
+                break;
+
+            case IXOR:
+            case LXOR:
+                lir.logicalXor(leftOp, rightOp, resultOp);
+                break;
+
+            default:
+                Util.shouldNotReachHere();
+        }
+    }
+
+    /*void moveToPhi(PhiResolver resolver, Value curVal, Value suxVal, List<Phi> phis, int predIndex) {
+        // move current value to referenced phi function
+        if (suxVal instanceof Phi) {
+            Phi phi = (Phi) suxVal;
+
+            // curVal can be null without phi being null in conjunction with inlining
+            if (!phi.isDead() && curVal != null && curVal != phi) {
+
+                assert phis.contains(phi);
+                if (phi.valueAt(predIndex) != curVal) {
+                    phi.print(TTY.out());
+                }
+                assert phi.valueAt(predIndex) == curVal : "curVal=" + curVal + "valueAt(" + predIndex + ")=" + phi.valueAt(predIndex);
+
+                assert !phi.isDead() : "illegal phi cannot be marked as live";
+                if (curVal instanceof Phi) {
+                    operandForPhi((Phi) curVal);
+                }
+                CiValue operand = curVal.operand();
+                if (operand.isIllegal()) {
+                    assert curVal instanceof Constant || curVal instanceof Local : "these can be produced lazily";
+                    operand = operandForInstruction(curVal);
+                }
+                resolver.move(operand, operandForPhi(phi));
+            }
+        }
+    }*/
+
+    @Override
+    public void visitEndNode(EndNode end) {
+        setNoResult(end);
+        assert end.merge() != null;
+        moveToPhi(end.merge(), end);
+        LIRBlock lirBlock = getLIRBlock(end.merge());
+        assert lirBlock != null : end;
+        lir.jump(lirBlock);
+    }
+
+    @Override
+    public void visitMemoryRead(ReadNode memRead) {
+        lir.move(memRead.location().createAddress(this, memRead.object()), createResultVariable(memRead), memRead.location().getValueKind());
+    }
+
+
+    @Override
+    public void visitMemoryWrite(WriteNode memWrite) {
+        lir.move(load(memWrite.value()), memWrite.location().createAddress(this, memWrite.object()), memWrite.location().getValueKind());
+    }
+
+
+    @Override
+    public void visitLoopEnd(LoopEnd x) {
+        setNoResult(x);
+        moveToPhi(x.loopBegin(), x);
+        if (GraalOptions.GenSafepoints) {
+            xir.genSafepoint(site(x));
+        }
+        lir.jump(getLIRBlock(x.loopBegin()));
+    }
+
+    private void moveToPhi(Merge merge, Node pred) {
+        if (GraalOptions.TraceLIRGeneratorLevel >= 1) {
+            TTY.println("MOVE TO PHI from " + pred + " to " + merge);
+        }
+        int nextSuccIndex = merge.phiPredecessorIndex(pred);
+        PhiResolver resolver = new PhiResolver(this);
+        for (Phi phi : merge.phis()) {
+            if (phi.type() == PhiType.Value) {
+                Value curVal = phi.valueAt(nextSuccIndex);
+                if (curVal != null && curVal != phi) {
+                    if (curVal instanceof Phi) {
+                        operandForPhi((Phi) curVal);
+                    }
+                    CiValue operand = curVal.operand();
+                    if (operand.isIllegal()) {
+                        assert curVal instanceof Constant || curVal instanceof Local : "these can be produced lazily" + curVal + "/" + phi;
+                        operand = operandForInstruction(curVal);
+                    }
+                    resolver.move(operand, operandForPhi(phi));
+                }
+            }
+        }
+        resolver.dispose();
+        //TODO (gd) remove that later ?
+        if (merge instanceof LoopBegin) {
+            LoopBegin loopBegin = (LoopBegin) merge;
+            for (LoopCounter counter : loopBegin.counters()) {
+                if (counter.operand().isIllegal()) {
+                    createResultVariable(counter);
+                }
+                if (nextSuccIndex == 0) {
+                    lir.move(operandForInstruction(counter.init()), counter.operand());
+                } else {
+                    if (counter.kind == CiKind.Int) {
+                        this.arithmeticOpInt(IADD, counter.operand(), counter.operand(), operandForInstruction(counter.stride()), CiValue.IllegalValue);
+                    } else {
+                        assert counter.kind == CiKind.Long;
+                        this.arithmeticOpLong(LADD, counter.operand(), counter.operand(), operandForInstruction(counter.stride()));
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Creates a new {@linkplain CiVariable variable}.
+     *
+     * @param kind the kind of the variable
+     * @return a new variable
+     */
+    public CiVariable newVariable(CiKind kind) {
+        return operands.newVariable(kind);
+    }
+
+    CiValue operandForInstruction(Value x) {
+        CiValue operand = x.operand();
+        if (operand.isIllegal()) {
+            if (x instanceof Constant) {
+                x.setOperand(x.asConstant());
+            } else {
+                assert x instanceof Phi || x instanceof Local : "only for Phi and Local : " + x;
+                // allocate a variable for this local or phi
+                createResultVariable(x);
+            }
+        }
+        return x.operand();
+    }
+
+    private CiValue operandForPhi(Phi phi) {
+        assert phi.type() == PhiType.Value : "wrong phi type: " + phi.id();
+        if (phi.operand().isIllegal()) {
+            // allocate a variable for this phi
+            createResultVariable(phi);
+        }
+        return phi.operand();
+    }
+
+    protected void postGCWriteBarrier(CiValue addr, CiValue newVal) {
+       XirSnippet writeBarrier = xir.genWriteBarrier(toXirArgument(addr));
+       if (writeBarrier != null) {
+           emitXir(writeBarrier, null, null, null, false);
+       }
+    }
+
+    protected void preGCWriteBarrier(CiValue addrOpr, boolean patch, LIRDebugInfo info) {
+    }
+
+    protected void setNoResult(Value x) {
+        x.clearOperand();
+    }
+
+    public CiValue setResult(Value x, CiVariable operand) {
+        x.setOperand(operand);
+        if (GraalOptions.DetailedAsserts) {
+            operands.recordResult(operand, x);
+        }
+        return operand;
+    }
+
+    protected void shiftOp(int code, CiValue resultOp, CiValue value, CiValue count, CiValue tmp) {
+        if (isTwoOperand && value != resultOp) {
+            assert count != resultOp : "malformed";
+            lir.move(value, resultOp);
+            value = resultOp;
+        }
+
+        assert count.isConstant() || count.isVariableOrRegister();
+        switch (code) {
+            case ISHL:
+            case LSHL:
+                lir.shiftLeft(value, count, resultOp, tmp);
+                break;
+            case ISHR:
+            case LSHR:
+                lir.shiftRight(value, count, resultOp, tmp);
+                break;
+            case IUSHR:
+            case LUSHR:
+                lir.unsignedShiftRight(value, count, resultOp, tmp);
+                break;
+            default:
+                Util.shouldNotReachHere();
+        }
+    }
+
+    protected void walkState(final Node x, FrameState state) {
+        if (state == null) {
+            return;
+        }
+
+        state.forEachLiveStateValue(new ValueProcedure() {
+            public void doValue(Value value) {
+                if (value == x) {
+                    // nothing to do, will be visited shortly
+                } else if (value instanceof Phi && ((Phi) value).type() == PhiType.Value) {
+                    // phi's are special
+                    operandForPhi((Phi) value);
+                } else if (value.operand().isIllegal()) {
+                    // instruction doesn't have an operand yet
+                    CiValue operand = makeOperand(value);
+                    assert operand.isLegal() : "must be evaluated now";
+                }
+            }
+        });
+    }
+
+    protected LIRDebugInfo stateFor(Value x) {
+        assert lastState != null : "must have state before instruction for " + x;
+        return stateFor(x, lastState);
+    }
+
+    protected LIRDebugInfo stateFor(Value x, FrameState state) {
+        if (compilation.placeholderState != null) {
+            state = compilation.placeholderState;
+        }
+        return new LIRDebugInfo(state);
+    }
+
+    List<CiValue> visitInvokeArguments(CiCallingConvention cc, Invoke x, List<CiValue> pointerSlots) {
+        // for each argument, load it into the correct location
+        List<CiValue> argList = new ArrayList<CiValue>();
+        int j = 0;
+        for (Value arg : x.arguments()) {
+            if (arg != null) {
+                CiValue operand = cc.locations[j++];
+                if (operand.isRegister()) {
+                    force(arg, operand);
+                } else {
+                    LIRItem param = new LIRItem(arg, this);
+                    assert operand.isStackSlot();
+                    CiStackSlot slot = (CiStackSlot) operand;
+                    assert !slot.inCallerFrame();
+                    param.loadForStore(slot.kind);
+                    if (slot.kind == CiKind.Long || slot.kind == CiKind.Double) {
+                        lir.unalignedMove(param.result(), slot);
+                    } else {
+                        lir.move(param.result(), slot);
+                    }
+
+                    if (arg.kind == CiKind.Object && pointerSlots != null) {
+                        // This slot must be marked explicitly in the pointer map.
+                        pointerSlots.add(slot);
+                    }
+                }
+                argList.add(operand);
+            }
+        }
+        return argList;
+    }
+
+    /**
+     * Ensures that an operand has been {@linkplain Value#setOperand(CiValue) initialized}
+     * for storing the result of an instruction.
+     *
+     * @param instruction an instruction that produces a result value
+     */
+    public CiValue makeOperand(Value instruction) {
+        if (instruction == null) {
+            return CiValue.IllegalValue;
+        }
+        CiValue operand = instruction.operand();
+        if (operand.isIllegal()) {
+            if (instruction instanceof Phi) {
+                // a phi may not have an operand yet if it is for an exception block
+                operand = operandForPhi((Phi) instruction);
+            } else if (instruction instanceof Constant) {
+                operand = operandForInstruction(instruction);
+            }
+        }
+        // the value must be a constant or have a valid operand
+        assert operand.isLegal() : "this root has not been visited yet; instruction=" + instruction + " currentBlock=" + currentBlock;
+        return operand;
+    }
+
+    /**
+     * 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}
+     */
+    protected CiValue resultOperandFor(CiKind kind) {
+        if (kind == CiKind.Void) {
+            return IllegalValue;
+        }
+        CiRegister returnRegister = compilation.registerConfig.getReturnRegister(kind);
+        return returnRegister.asValue(kind);
+    }
+
+    protected XirSupport site(Value x) {
+        return xirSupport.site(x);
+    }
+
+    public void maybePrintCurrentInstruction() {
+        if (currentInstruction != null && lastInstructionPrinted != currentInstruction) {
+            lastInstructionPrinted = currentInstruction;
+            InstructionPrinter ip = new InstructionPrinter(TTY.out());
+            ip.printInstructionListing(currentInstruction);
+        }
+    }
+
+    protected abstract boolean canInlineAsConstant(Value i);
+
+    protected abstract boolean canStoreAsConstant(Value i, CiKind kind);
+
+    protected abstract boolean strengthReduceMultiply(CiValue left, int constant, CiValue result, CiValue tmp);
+
+    protected abstract CiAddress genAddress(CiValue base, CiValue index, int shift, int disp, CiKind kind);
+
+    protected abstract void genCmpMemInt(Condition condition, CiValue base, int disp, int c, LIRDebugInfo info);
+
+    protected abstract void genCmpRegMem(Condition condition, CiValue reg, CiValue base, int disp, CiKind kind, LIRDebugInfo info);
+
+    /**
+     * Implements site-specific information for the XIR interface.
+     */
+    static class XirSupport implements XirSite {
+        Value current;
+
+        XirSupport() {
+        }
+
+        public CiCodePos getCodePos() {
+            // TODO: get the code position of the current instruction if possible
+            return null;
+        }
+
+        public boolean isNonNull(XirArgument argument) {
+            return false;
+        }
+
+        public boolean requiresNullCheck() {
+            return current == null || true;
+        }
+
+        public boolean requiresBoundsCheck() {
+            return true;
+        }
+
+        public boolean requiresReadBarrier() {
+            return current == null || true;
+        }
+
+        public boolean requiresWriteBarrier() {
+            return current == null || true;
+        }
+
+        public boolean requiresArrayStoreCheck() {
+            return true;
+        }
+
+        public RiType getApproximateType(XirArgument argument) {
+            return current == null ? null : current.declaredType();
+        }
+
+        public RiType getExactType(XirArgument argument) {
+            return current == null ? null : current.exactType();
+        }
+
+        XirSupport site(Value v) {
+            current = v;
+            return this;
+        }
+
+        @Override
+        public String toString() {
+            return "XirSupport<" + current + ">";
+        }
+
+
+    }
+
+    @Override
+    public void visitFrameState(FrameState i) {
+        // nothing to do for now
+    }
+
+    @Override
+    public void visitUnwind(Unwind x) {
+        // move exception oop into fixed register
+        CiCallingConvention callingConvention = compilation.frameMap().getCallingConvention(new CiKind[]{CiKind.Object}, RuntimeCall);
+        CiValue argumentOperand = callingConvention.locations[0];
+        lir.move(makeOperand(x.exception()), argumentOperand);
+        List<CiValue> args = new ArrayList<CiValue>(1);
+        lir.callRuntime(CiRuntimeCall.UnwindException, CiValue.IllegalValue, args, null);
+        setNoResult(x);
+    }
+
+    public interface LIRGeneratorOp extends Op {
+        void generate(Node n, LIRGenerator generator);
+    }
+
+    public static final LIRGeneratorOp DELEGATE_TO_VALUE_VISITOR = new LIRGeneratorOp() {
+        @Override
+        public void generate(Node n, LIRGenerator generator) {
+            ((Value) n).accept(generator);
+        }
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRItem.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.gen;
+
+import com.oracle.max.graal.compiler.alloc.OperandPool.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.sun.cri.ci.*;
+
+/**
+ * A helper utility for loading the {@linkplain Value#operand() result}
+ * of an instruction for use by another instruction. This helper takes
+ * into account the specifics of the consuming instruction such as whether
+ * it requires the input operand to be in memory or a register, any
+ * register size requirements of the input operand, and whether the
+ * usage has the side-effect of overwriting the input operand. To satisfy
+ * these constraints, an intermediate operand may be created and move
+ * instruction inserted to copy the output of the producer instruction
+ * into the intermediate operand.
+ *
+ * @author Marcelo Cintra
+ * @author Thomas Wuerthinger
+ * @author Doug Simon
+ */
+public class LIRItem {
+
+    /**
+     * The instruction whose usage by another instruction is being modeled by this object.
+     * An instruction {@code x} uses instruction {@code y} if the {@linkplain Value#operand() result}
+     * of {@code y} is an input operand of {@code x}.
+     */
+    public Value instruction;
+
+    /**
+     * The LIR context of this helper object.
+     */
+    private final LIRGenerator gen;
+
+    /**
+     * The operand holding the result of this item's {@linkplain #instruction}.
+     */
+    private CiValue resultOperand;
+
+    /**
+     * Denotes if the use of the instruction's {@linkplain #resultOperand result operand}
+     * overwrites the value in the operand. That is, the use both uses and defines the
+     * operand. In this case, an {@linkplain #intermediateOperand intermediate operand}
+     * is created for the use so that other consumers of this item's {@linkplain #instruction}
+     * are not impacted.
+     */
+    private boolean destructive;
+
+    /**
+     * @see #destructive
+     */
+    private CiValue intermediateOperand;
+
+    public LIRItem(Value instruction, LIRGenerator gen) {
+        this.gen = gen;
+        this.instruction = instruction;
+        resultOperand = gen.makeOperand(instruction);
+        intermediateOperand = CiValue.IllegalValue;
+    }
+
+    public void loadForStore(CiKind kind) {
+        if (gen.canStoreAsConstant(instruction, kind)) {
+            resultOperand = instruction.operand();
+            if (!resultOperand.isConstant()) {
+                resultOperand = instruction.asConstant();
+            }
+        } else if (kind == CiKind.Byte || kind == CiKind.Boolean) {
+            loadByteItem();
+        } else {
+            loadItem();
+        }
+    }
+
+    public CiValue result() {
+        assert !destructive || !resultOperand.isRegister() : "shouldn't use setDestroysRegister with physical registers";
+        if (destructive && (resultOperand.isVariable() || resultOperand.isConstant())) {
+            if (intermediateOperand.isIllegal()) {
+                intermediateOperand = gen.newVariable(instruction.kind);
+                gen.lir.move(resultOperand, intermediateOperand);
+            }
+            return intermediateOperand;
+        } else {
+            return resultOperand;
+        }
+    }
+
+    public void setDestroysRegister() {
+        destructive = true;
+    }
+
+    /**
+     * Determines if the operand is in a stack slot.
+     */
+    public boolean isStack() {
+        return resultOperand.isAddress() || resultOperand.isStackSlot();
+    }
+
+    /**
+     * Determines if the operand is in a register or may be
+     * resolved to a register by the register allocator.
+     */
+    public boolean isRegisterOrVariable() {
+        return resultOperand.isVariableOrRegister();
+    }
+
+    public void loadByteItem() {
+        if (gen.compilation.target.arch.isX86()) {
+            loadItem();
+            CiValue res = result();
+
+            if (!res.isVariable() || !gen.operands.mustBeByteRegister(res)) {
+                // make sure that it is a byte register
+                assert !instruction.kind.isFloat() && !instruction.kind.isDouble() : "can't load floats in byte register";
+                CiValue reg = gen.operands.newVariable(CiKind.Byte, VariableFlag.MustBeByteRegister);
+                gen.lir.move(res, reg);
+                resultOperand = reg;
+            }
+        } else if (gen.compilation.target.arch.isSPARC()) {
+            loadItem();
+        } else {
+            Util.shouldNotReachHere();
+        }
+    }
+
+    public void loadNonconstant() {
+        assert gen.compilation.target.arch.isX86();
+        CiValue r = instruction.operand();
+        if (r.isConstant()) {
+            resultOperand = r;
+        } else {
+            loadItem();
+        }
+    }
+
+    private void setResult(CiVariable operand) {
+        gen.setResult(instruction, operand);
+        resultOperand = operand;
+    }
+
+    /**
+     * Creates an operand containing the result of {@linkplain #instruction input instruction}.
+     */
+    public void loadItem() {
+        if (result().isIllegal()) {
+            // update the item's result
+            resultOperand = instruction.operand();
+        }
+        CiValue result = result();
+        if (!result.isVariableOrRegister()) {
+            CiVariable operand;
+            operand = gen.newVariable(instruction.kind);
+            gen.lir.move(result, operand);
+            if (result.isConstant()) {
+                resultOperand = operand;
+            } else {
+                setResult(operand);
+            }
+        }
+    }
+
+    @Override
+    public String toString() {
+        return result().toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/PhiResolver.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.gen;
+
+import static com.sun.cri.ci.CiValue.*;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.ir.*;
+import com.sun.cri.ci.*;
+
+/**
+ * Converts {@link Phi} instructions into moves.
+ *
+ * Resolves cycles:
+ * <pre>
+ *
+ *  r1 := r2  becomes  temp := r1
+ *  r2 := r1           r1 := r2
+ *                     r2 := temp
+ * </pre>
+ *
+ * and orders moves:
+ *
+ * <pre>
+ *  r2 := r3  becomes  r1 := r2
+ *  r1 := r2           r2 := r3
+ * </pre>
+ */
+public class PhiResolver {
+
+    /**
+     * Tracks a data flow dependency between a source operand and any number of the destination operands.
+     */
+    static class PhiResolverNode {
+
+        /**
+         * A source operand whose value flows into the {@linkplain #destinations destination} operands.
+         */
+        final CiValue operand;
+
+        /**
+         * The operands whose values are defined by the {@linkplain #operand source} operand.
+         */
+        final ArrayList<PhiResolverNode> destinations;
+
+        /**
+         * Denotes if a move instruction has already been emitted to initialize the value of {@link #operand}.
+         */
+        boolean assigned;
+
+        /**
+         * Specifies if this operand been visited for the purpose of emitting a move instruction.
+         */
+        boolean visited;
+
+        /**
+         * Specifies if this is the initial definition in data flow path for a given value.
+         */
+        boolean startNode;
+
+        PhiResolverNode(CiValue operand) {
+            this.operand = operand;
+            destinations = new ArrayList<PhiResolverNode>(4);
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder buf = new StringBuilder(operand.toString());
+            if (!destinations.isEmpty()) {
+                buf.append(" ->");
+                for (PhiResolverNode node : destinations) {
+                    buf.append(' ').append(node.operand);
+                }
+            }
+            return buf.toString();
+        }
+    }
+
+    private final LIRGenerator gen;
+
+    /**
+     * The operand loop header phi for the operand currently being process in {@link #dispose()}.
+     */
+    private PhiResolverNode loop;
+
+    private CiValue temp;
+
+    private final ArrayList<PhiResolverNode> variableOperands = new ArrayList<PhiResolverNode>(3);
+    private final ArrayList<PhiResolverNode> otherOperands = new ArrayList<PhiResolverNode>(3);
+
+    /**
+     * Maps operands to nodes.
+     */
+    private final HashMap<CiValue, PhiResolverNode> operandToNodeMap = new HashMap<CiValue, PhiResolverNode>();
+
+    public PhiResolver(LIRGenerator gen) {
+        this.gen = gen;
+        temp = IllegalValue;
+    }
+
+    public void dispose() {
+        // resolve any cycles in moves from and to variables
+        for (int i = variableOperands.size() - 1; i >= 0; i--) {
+            PhiResolverNode node = variableOperands.get(i);
+            if (!node.visited) {
+                loop = null;
+                move(null, node);
+                node.startNode = true;
+                assert temp.isIllegal() : "moveTempTo() call missing";
+            }
+        }
+
+        // generate move for move from non variable to arbitrary destination
+        for (int i = otherOperands.size() - 1; i >= 0; i--) {
+            PhiResolverNode node = otherOperands.get(i);
+            for (int j = node.destinations.size() - 1; j >= 0; j--) {
+                emitMove(node.operand, node.destinations.get(j).operand);
+            }
+        }
+    }
+
+    public void move(CiValue src, CiValue dest) {
+        assert dest.isVariable() : "destination must be virtual";
+        // tty.print("move "); src.print(); tty.print(" to "); dest.print(); tty.cr();
+        assert src.isLegal() : "source for phi move is illegal";
+        assert dest.isLegal() : "destination for phi move is illegal";
+        PhiResolverNode srcNode = sourceNode(src);
+        PhiResolverNode destNode = destinationNode(dest);
+        srcNode.destinations.add(destNode);
+      }
+
+    private PhiResolverNode createNode(CiValue operand, boolean source) {
+        PhiResolverNode node;
+        if (operand.isVariable()) {
+            node = operandToNodeMap.get(operand);
+            assert node == null || node.operand.equals(operand);
+            if (node == null) {
+                node = new PhiResolverNode(operand);
+                operandToNodeMap.put(operand, node);
+            }
+            // Make sure that all variables show up in the list when
+            // they are used as the source of a move.
+            if (source) {
+                if (!variableOperands.contains(node)) {
+                    variableOperands.add(node);
+                }
+            }
+        } else {
+            assert source;
+            node = new PhiResolverNode(operand);
+            otherOperands.add(node);
+        }
+        return node;
+    }
+
+    private PhiResolverNode destinationNode(CiValue opr) {
+        return createNode(opr, false);
+    }
+
+    private void emitMove(CiValue src, CiValue dest) {
+        assert src.isLegal();
+        assert dest.isLegal();
+        gen.lir.move(src, dest);
+    }
+
+    // Traverse assignment graph in depth first order and generate moves in post order
+    // ie. two assignments: b := c, a := b start with node c:
+    // Call graph: move(NULL, c) -> move(c, b) -> move(b, a)
+    // Generates moves in this order: move b to a and move c to b
+    // ie. cycle a := b, b := a start with node a
+    // Call graph: move(NULL, a) -> move(a, b) -> move(b, a)
+    // Generates moves in this order: move b to temp, move a to b, move temp to a
+    private void move(PhiResolverNode src, PhiResolverNode dest) {
+        if (!dest.visited) {
+            dest.visited = true;
+            for (int i = dest.destinations.size() - 1; i >= 0; i--) {
+                move(dest, dest.destinations.get(i));
+            }
+        } else if (!dest.startNode) {
+            // cycle in graph detected
+            assert loop == null : "only one loop valid!";
+            loop = dest;
+            moveToTemp(src.operand);
+            return;
+        } // else dest is a start node
+
+        if (!dest.assigned) {
+            if (loop == dest) {
+                moveTempTo(dest.operand);
+                dest.assigned = true;
+            } else if (src != null) {
+                emitMove(src.operand, dest.operand);
+                dest.assigned = true;
+            }
+        }
+    }
+
+    private void moveTempTo(CiValue dest) {
+        assert temp.isLegal();
+        emitMove(temp, dest);
+        temp = IllegalValue;
+    }
+
+    private void moveToTemp(CiValue src) {
+        assert temp.isIllegal();
+        temp = gen.newVariable(src.kind);
+        emitMove(src, temp);
+    }
+
+    private PhiResolverNode sourceNode(CiValue opr) {
+        return createNode(opr, true);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/PhiSimplifier.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.gen;
+
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.graph.*;
+
+/**
+ * The {@code PhiSimplifier} class is a helper class that can reduce phi instructions.
+ */
+public final class PhiSimplifier {
+
+    private NodeBitMap visited;
+    private NodeBitMap cannotSimplify;
+
+    public PhiSimplifier(Graph graph) {
+        visited = graph.createNodeBitMap();
+        cannotSimplify = graph.createNodeBitMap();
+
+        for (Node n : graph.getNodes()) {
+            if (n instanceof Phi) {
+                simplify((Phi) n);
+            }
+        }
+    }
+
+    private Value simplify(Value x) {
+        if (x == null || !(x instanceof Phi)) {
+            return x;
+        }
+        Phi phi = (Phi) x;
+
+        if (phi.valueCount() == 1 && !cannotSimplify.isMarked(phi)) {
+            Value result = phi.valueAt(0);
+            phi.replaceAndDelete(result);
+            return result;
+        }
+
+        if (cannotSimplify.isMarked(phi)) {
+            // already tried, cannot simplify this phi
+            return phi;
+        } else if (visited.isMarked(phi)) {
+            // break cycles in phis
+            return phi;
+        } else {
+            // attempt to simplify the phi by recursively simplifying its operands
+            visited.mark(phi);
+            Value phiSubst = null;
+            int max = phi.valueCount();
+            boolean cannotSimplify = false;
+            for (int i = 0; i < max; i++) {
+                Value oldInstr = phi.valueAt(i);
+
+                if (oldInstr == null) {
+                    // if one operand is illegal, make the entire phi illegal
+                    visited.clear(phi);
+                    phi.replaceAndDelete(null);
+                    return null;
+                }
+
+                Value newInstr = simplify(oldInstr);
+
+                if (newInstr == null) {
+                    // if the subst instruction is illegal, make the entire phi illegal
+                    visited.clear(phi);
+                    phi.replaceAndDelete(null);
+                    return null;
+                }
+
+                // attempt to simplify this operand
+                if (!cannotSimplify) {
+
+                    if (newInstr != phi && newInstr != phiSubst) {
+                        if (phiSubst == null) {
+                            phiSubst = newInstr;
+                            continue;
+                        }
+                        // this phi cannot be simplified
+                        cannotSimplify = true;
+                    }
+                }
+            }
+            if (cannotSimplify) {
+                this.cannotSimplify.mark(phi);
+                visited.clear(phi);
+                return phi;
+            }
+
+            // successfully simplified the phi
+            assert phiSubst != null : "illegal phi function";
+            visited.clear(phi);
+
+            phi.replaceAndDelete(phiSubst);
+
+            return phiSubst;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/package-info.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/**
+ * This package contains the port of the LIRGenerator which translates
+ * HIR instructions to LIR instructions for the backend.
+ *
+ * @author Marcelo Cintra
+ * @author Thomas Wuerthinger
+ */
+package com.oracle.max.graal.compiler.gen;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/globalstub/GlobalStub.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.globalstub;
+
+import static com.sun.cri.ci.CiKind.*;
+
+import com.sun.cri.ci.*;
+
+/**
+ * A global stub is a shared routine that performs an operation on behalf of compiled code.
+ * Typically the routine is too large to inline, is infrequent, or requires runtime support.
+ * Global stubs are called with a callee-save convention; the global stub must save any
+ * registers it may destroy and then restore them upon return. This allows the register
+ * allocator to ignore calls to global stubs. Parameters to global stubs are
+ * passed on the stack in order to preserve registers for the rest of the code.
+ *
+ * @author Thomas Wuerthinger
+ * @author Ben L. Titzer
+ */
+public class GlobalStub {
+
+    public enum Id {
+
+        fneg(Float, Float),
+        dneg(Double, Double),
+        f2i(Int, Float),
+        f2l(Long, Float),
+        d2i(Int, Double),
+        d2l(Long, Double);
+
+        public final CiKind resultKind;
+        public final CiKind[] arguments;
+
+        private Id(CiKind resultKind, CiKind... args) {
+            this.resultKind = resultKind;
+            this.arguments = args;
+        }
+    }
+
+    public final Id id;
+    public final CiKind resultKind;
+    public final Object stubObject;
+    public final int argsSize;
+    public final int[] argOffsets;
+    public final int resultOffset;
+
+    public GlobalStub(Id id, CiKind resultKind, Object stubObject, int argsSize, int[] argOffsets, int resultOffset) {
+        this.id = id;
+        this.resultKind = resultKind;
+        this.stubObject = stubObject;
+        this.argsSize = argsSize;
+        this.argOffsets = argOffsets;
+        this.resultOffset = resultOffset;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/globalstub/GlobalStubEmitter.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.globalstub;
+
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+import com.sun.cri.xir.*;
+
+/**
+ * An interface to represent the entity that generates stubs.
+ *
+ * @author Thomas Wuerthinger
+ * @author Ben L. Titzer
+ */
+public interface GlobalStubEmitter {
+    GlobalStub emit(GlobalStub.Id stub, RiRuntime runtime);
+    GlobalStub emit(CiRuntimeCall runtimeCall, RiRuntime runtime);
+    GlobalStub emit(XirTemplate t, RiRuntime runtime);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/BlockMap.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,699 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.graph;
+
+import static com.sun.cri.bytecode.Bytecodes.*;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * Builds a mapping between bytecodes and basic blocks and builds a conservative control flow
+ * graph. Note that this class serves a similar role to C1's {@code BlockListBuilder}, but makes fewer assumptions about
+ * what the compiler interface provides. It builds all basic blocks for the control flow graph without requiring the
+ * compiler interface to provide a bitmap of the beginning of basic blocks. It makes two linear passes; one over the
+ * bytecodes to build block starts and successor lists, and one pass over the block map to build the CFG.
+ *
+ * Note that the CFG built by this class is <i>not</i> connected to the actual {@code BlockBegin} instances; this class
+ * does, however, compute and assign the reverse postorder number of the blocks. This comment needs refinement. (MJJ)
+ *
+ * <H2>More Details on {@link BlockMap#build}</H2>
+ *
+ * If the method has any exception handlers the {@linkplain #exceptionMap exception map} will be created (TBD).
+ *
+ * The bytecodes are then scanned linearly looking for bytecodes that contain control transfers, e.g., {@code GOTO},
+ * {@code RETURN}, {@code IFGE}, and creating the corresponding entries in {@link #successorMap} and {@link #blockMap}.
+ * In addition, if {@link #exceptionMap} is not null, entries are made for any bytecode that can cause an exception.
+ * More TBD.
+ *
+ * Observe that this process finds bytecodes that terminate basic blocks, so the {@link #moveSuccessorLists} method is
+ * called to reassign the successors to the {@code BlockBegin} node that actually starts the block.
+ *
+ * <H3>Example</H3>
+ *
+ * Consider the following source code:
+ *
+ * <pre>
+ * <code>
+ *     public static int test(int arg1, int arg2) {
+ *         int x = 0;
+ *         while (arg2 > 0) {
+ *             if (arg1 > 0) {
+ *                 x += 1;
+ *             } else if (arg1 < 0) {
+ *                 x -= 1;
+ *             }
+ *         }
+ *         return x;
+ *     }
+ * </code>
+ * </pre>
+ *
+ * This is translated by javac to the following bytecode:
+ *
+ * <pre>
+ * <code>
+ *    0:   iconst_0
+ *    1:   istore_2
+ *    2:   goto    22
+ *    5:   iload_0
+ *    6:   ifle    15
+ *    9:   iinc    2, 1
+ *    12:  goto    22
+ *    15:  iload_0
+ *    16:  ifge    22
+ *    19:  iinc    2, -1
+ *    22:  iload_1
+ *    23:  ifgt    5
+ *    26:  iload_2
+ *    27:  ireturn
+ *    </code>
+ * </pre>
+ *
+ * There are seven basic blocks in this method, 0..2, 5..6, 9..12, 15..16, 19..19, 22..23 and 26..27. Therefore, before
+ * the call to {@code moveSuccessorLists}, the {@code blockMap} array has {@code BlockBegin} nodes at indices 0, 5, 9,
+ * 15, 19, 22 and 26. The {@code successorMap} array has entries at 2, 6, 12, 16, 23, 27 corresponding to the control
+ * transfer bytecodes. The entry at index 6, for example, is a length two array of {@code BlockBegin} nodes for indices
+ * 9 and 15, which are the successors for the basic block 5..6. After the call to {@code moveSuccessors}, {@code
+ * successorMap} has entries at 0, 5, 9, 15, 19, 22 and 26, i.e, matching {@code blockMap}.
+ * <p>
+ * Next the blocks are numbered using <a href="http://en.wikipedia.org/wiki/Depth-first_search#Vertex_orderings">reverse
+ * post-order</a>. For the above example this results in the numbering 2, 4, 7, 5, 6, 3, 8. Also loop header blocks are
+ * detected during the traversal by detecting a repeat visit to a block that is still being processed. This causes the
+ * block to be flagged as a loop header and also added to the {@link #loopBlocks} list. The {@code loopBlocks} list
+ * contains the blocks at 0, 5, 9, 15, 19, 22, with 22 as the loop header. (N.B. the loop header block is added multiple
+ * (4) times to this list). (Should 0 be in? It's not inside the loop).
+ *
+ * If the {@code computeStoresInLoops} argument to {@code build} is true, the {@code loopBlocks} list is processed to
+ * mark all local variables that are stored in the blocks in the list.
+ */
+public final class BlockMap {
+    public static class Block {
+        public int startBci;
+        public int endBci;
+        public boolean isExceptionEntry;
+        public boolean isLoopHeader;
+        public int blockID;
+
+        public FixedNodeWithNext firstInstruction;
+
+        final HashSet<Block> successors = new LinkedHashSet<Block>();
+        private boolean visited;
+        private boolean active;
+        private long loops;
+    }
+
+    public static class ExceptionBlock  extends Block {
+        public RiExceptionHandler handler;
+        public Block next;
+        public int deoptBci;
+    }
+
+    public static class DeoptBlock  extends Block {
+    }
+
+    public static class BranchOverride {
+        public DeoptBlock block;
+        public boolean taken;
+    }
+
+    private static final Block[] NO_SUCCESSORS = new Block[0];
+
+    /**
+     * The blocks found in this method, in reverse postorder.
+     */
+    public final List<Block> blocks;
+
+    /**
+     * A bit map covering the locals with a bit set for each local that might be stored to within a
+     * loop. If the bit is cleared, it is guaranteed that the local is never stored in a loop.
+     */
+    public final BitSet storesInLoops;
+
+    private final RiMethod method;
+
+    private final RiExceptionHandler[] exceptionHandlers;
+
+    public final HashMap<Integer, BranchOverride> branchOverride;
+
+    private Block[] blockMap;
+
+    private BitSet canTrap;
+
+    /**
+     * Creates a new BlockMap instance from bytecode of the given method .
+     * @param method the compiler interface method containing the code
+     */
+    public BlockMap(RiMethod method) {
+        this.method = method;
+        exceptionHandlers = method.exceptionHandlers();
+        this.blockMap = new Block[method.codeSize()];
+        if (method.exceptionHandlers().length != 0) {
+            this.canTrap = new BitSet(blockMap.length);
+        }
+        this.blocks = new ArrayList<Block>();
+        this.storesInLoops = new BitSet(method.maxLocals());
+        branchOverride = new HashMap<Integer, BranchOverride>();
+    }
+
+    public RiExceptionHandler[] exceptionHandlers() {
+        return exceptionHandlers;
+    }
+
+    /**
+     * Builds the block map and conservative CFG and numbers blocks.
+     */
+    public void build() {
+        makeExceptionEntries();
+        iterateOverBytecodes();
+        addExceptionEdges();
+        computeBlockOrder();
+
+        initializeBlockIds();
+
+        // Discard big arrays so that they can be GCed
+        blockMap = null;
+        canTrap = null;
+    }
+
+    private void initializeBlockIds() {
+        for (int i = 0; i < blocks.size(); i++) {
+            blocks.get(i).blockID = i;
+        }
+    }
+
+    private void makeExceptionEntries() {
+        // start basic blocks at all exception handler blocks and mark them as exception entries
+        for (RiExceptionHandler h : this.exceptionHandlers) {
+            Block xhandler = makeBlock(h.handlerBCI());
+            xhandler.isExceptionEntry = true;
+        }
+    }
+
+    private void iterateOverBytecodes() {
+        // iterate over the bytecodes top to bottom.
+        // mark the entrypoints of basic blocks and build lists of successors for
+        // all bytecodes that end basic blocks (i.e. goto, ifs, switches, throw, jsr, returns, ret)
+        byte[] code = method.code();
+        Block current = null;
+        int bci = 0;
+        while (bci < code.length) {
+            if (current == null || blockMap[bci] != null) {
+                Block b = makeBlock(bci);
+                if (current != null) {
+                    setSuccessors(current.endBci, b);
+                }
+                current = b;
+            }
+            blockMap[bci] = current;
+            current.endBci = bci;
+
+            int opcode = Bytes.beU1(code, bci);
+            switch (opcode) {
+                case IRETURN: // fall through
+                case LRETURN: // fall through
+                case FRETURN: // fall through
+                case DRETURN: // fall through
+                case ARETURN: // fall through
+                case WRETURN: // fall through
+                case RETURN: {
+                    current = null;
+
+                    assert lengthOf(code, bci) == 1;
+                    bci += 1;
+                    break;
+                }
+
+                case ATHROW: {
+                    current = null;
+                    if (canTrap != null) {
+                        canTrap.set(bci);
+                    }
+
+                    assert lengthOf(code, bci) == 1;
+                    bci += 1;
+                    break;
+                }
+
+                case IFEQ:      // fall through
+                case IFNE:      // fall through
+                case IFLT:      // fall through
+                case IFGE:      // fall through
+                case IFGT:      // fall through
+                case IFLE:      // fall through
+                case IF_ICMPEQ: // fall through
+                case IF_ICMPNE: // fall through
+                case IF_ICMPLT: // fall through
+                case IF_ICMPGE: // fall through
+                case IF_ICMPGT: // fall through
+                case IF_ICMPLE: // fall through
+                case IF_ACMPEQ: // fall through
+                case IF_ACMPNE: // fall through
+                case IFNULL:    // fall through
+                case IFNONNULL: {
+                    current = null;
+
+                    double probability = GraalOptions.UseBranchPrediction ? method.branchProbability(bci) : -1;
+
+                    Block b1 = probability == 1.0 ? makeBranchOverrideBlock(bci, bci + 3, false) : makeBlock(bci + 3);
+                    Block b2 = probability == 0.0 ? makeBranchOverrideBlock(bci, bci + Bytes.beS2(code, bci + 1), true) : makeBlock(bci + Bytes.beS2(code, bci + 1));
+                    setSuccessors(bci, b1, b2);
+
+                    assert lengthOf(code, bci) == 3;
+                    bci += 3;
+                    break;
+                }
+
+                case GOTO: {
+                    current = null;
+                    Block b1 = makeBlock(bci + Bytes.beS2(code, bci + 1));
+                    setSuccessors(bci, b1);
+
+                    assert lengthOf(code, bci) == 3;
+                    bci += 3;
+                    break;
+                }
+
+                case GOTO_W: {
+                    current = null;
+                    Block b1 = makeBlock(bci + Bytes.beS4(code, bci + 1));
+                    setSuccessors(bci, b1);
+
+                    assert lengthOf(code, bci) == 5;
+                    bci += 5;
+                    break;
+                }
+
+                case TABLESWITCH: {
+                    BytecodeTableSwitch sw = new BytecodeTableSwitch(code, bci);
+                    setSuccessors(bci, makeSwitchSuccessors(sw));
+                    current = null;
+
+                    assert lengthOf(code, bci) == sw.size();
+                    bci += sw.size();
+                    break;
+                }
+
+                case LOOKUPSWITCH: {
+                    current = null;
+                    BytecodeLookupSwitch sw = new BytecodeLookupSwitch(code, bci);
+                    setSuccessors(bci, makeSwitchSuccessors(sw));
+
+                    assert lengthOf(code, bci) == sw.size();
+                    bci += sw.size();
+                    break;
+                }
+
+                case JSR: {
+                    throw new JSRNotSupportedBailout();
+                }
+                case JSR_W: {
+                    throw new JSRNotSupportedBailout();
+                }
+                case RET: {
+                    throw new JSRNotSupportedBailout();
+                }
+
+                case WIDE: {
+                    bci += lengthOf(code, bci);
+                    break;
+                }
+
+                default: {
+                    if (canTrap != null && canTrap(opcode)) {
+                        canTrap.set(bci);
+                    }
+
+                    assert lengthOf(code, bci) == lengthOf(opcode);
+                    bci += lengthOf(opcode);
+                }
+            }
+        }
+    }
+
+    public static boolean canTrap(int opcode) {
+        switch (opcode) {
+            case INVOKESTATIC:
+            case INVOKESPECIAL:
+            case INVOKEVIRTUAL:
+            case INVOKEINTERFACE: {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private Block makeBlock(int startBci) {
+        Block oldBlock = blockMap[startBci];
+        if (oldBlock == null) {
+            Block newBlock = new Block();
+            newBlock.startBci = startBci;
+            blockMap[startBci] = newBlock;
+            return newBlock;
+
+        } else if (oldBlock.startBci != startBci) {
+            // Backward branch into the middle of an already processed block.
+            // Add the correct fall-through successor.
+            Block newBlock = new Block();
+            newBlock.startBci = startBci;
+            newBlock.endBci = oldBlock.endBci;
+            newBlock.successors.addAll(oldBlock.successors);
+
+            oldBlock.endBci = startBci - 1;
+            oldBlock.successors.clear();
+            oldBlock.successors.add(newBlock);
+
+            for (int i = startBci; i <= newBlock.endBci; i++) {
+                blockMap[i] = newBlock;
+            }
+            return newBlock;
+
+        } else {
+            return oldBlock;
+        }
+    }
+
+    private Block makeBranchOverrideBlock(int branchBci, int startBci, boolean taken) {
+        DeoptBlock newBlock = new DeoptBlock();
+        newBlock.startBci = startBci;
+        BranchOverride override = new BranchOverride();
+        override.block = newBlock;
+        override.taken = taken;
+        assert branchOverride.get(branchBci) == null;
+        branchOverride.put(branchBci, override);
+        return newBlock;
+    }
+
+    private Block[] makeSwitchSuccessors(BytecodeSwitch tswitch) {
+        int max = tswitch.numberOfCases();
+        Block[] successors = new Block[max + 1];
+        for (int i = 0; i < max; i++) {
+            successors[i] = makeBlock(tswitch.targetAt(i));
+        }
+        successors[max] = makeBlock(tswitch.defaultTarget());
+        return successors;
+    }
+
+    private void setSuccessors(int predBci, Block... successors) {
+        for (Block sux : successors) {
+            if (sux.isExceptionEntry) {
+                throw new CiBailout("Exception handler can be reached by both normal and exceptional control flow");
+            }
+        }
+        Block predecessor = blockMap[predBci];
+        assert predecessor.successors.size() == 0;
+        predecessor.successors.addAll(Arrays.asList(successors));
+    }
+
+    private HashMap<RiExceptionHandler, ExceptionBlock> exceptionDispatch = new HashMap<RiExceptionHandler, ExceptionBlock>();
+
+    private ExceptionBlock unwindBlock;
+
+    private Block makeExceptionDispatch(List<RiExceptionHandler> handlers, int index, int bci) {
+        RiExceptionHandler handler = handlers.get(index);
+        if (handler.isCatchAll()) {
+            return blockMap[handler.handlerBCI()];
+        }
+        ExceptionBlock block = exceptionDispatch.get(handler);
+        if (block == null) {
+            block = new ExceptionBlock();
+            block.startBci = -1;
+            block.endBci = -1;
+            block.deoptBci = bci;
+            block.handler = handler;
+            block.successors.add(blockMap[handler.handlerBCI()]);
+            if (index < handlers.size() - 1) {
+                block.next = makeExceptionDispatch(handlers, index + 1, bci);
+                block.successors.add(block.next);
+            }
+            exceptionDispatch.put(handler, block);
+        }
+        return block;
+    }
+
+    private void addExceptionEdges() {
+        if (canTrap == null) {
+            return;
+        }
+
+        for (int bci = canTrap.nextSetBit(0); bci >= 0; bci = canTrap.nextSetBit(bci + 1)) {
+            Block block = blockMap[bci];
+
+            ArrayList<RiExceptionHandler> handlers = null;
+            for (RiExceptionHandler h : this.exceptionHandlers) {
+                if (h.startBCI() <= bci && bci < h.endBCI()) {
+                    if (handlers == null) {
+                        handlers = new ArrayList<RiExceptionHandler>();
+                    }
+                    handlers.add(h);
+                    if (h.isCatchAll()) {
+                        break;
+                    }
+                }
+            }
+            if (handlers != null) {
+                Block dispatch = makeExceptionDispatch(handlers, 0, bci);
+                block.successors.add(dispatch);
+            }
+        }
+    }
+
+    private void computeBlockOrder() {
+        long loop = computeBlockOrder(blockMap[0]);
+
+        if (loop != 0) {
+            // There is a path from a loop end to the method entry that does not pass the loop header.
+            // Therefore, the loop is non reducible (has more than one entry).
+            // We don't want to compile such methods because the IR only supports structured loops.
+            throw new CiBailout("Non-reducible loop");
+        }
+
+        // Convert postorder to the desired reverse postorder.
+        Collections.reverse(blocks);
+    }
+
+    /**
+     * The next available loop number.
+     */
+    private int nextLoop;
+
+    /**
+     * Mark the block as a loop header, using the next available loop number.
+     * Also checks for corner cases that we don't want to compile.
+     */
+    private void makeLoopHeader(Block block) {
+        if (!block.isLoopHeader) {
+            block.isLoopHeader = true;
+
+            if (block.isExceptionEntry) {
+                // Loops that are implicitly formed by an exception handler lead to all sorts of corner cases.
+                // Don't compile such methods for now, until we see a concrete case that allows checking for correctness.
+                throw new CiBailout("Loop formed by an exception handler");
+            }
+            if (nextLoop >= Long.SIZE) {
+                // This restriction can be removed by using a fall-back to a BitSet in case we have more than 32 loops
+                // Don't compile such methods for now, until we see a concrete case that allows checking for correctness.
+                throw new CiBailout("Too many loops in method");
+            }
+
+            assert block.loops == 0;
+            block.loops = (long) 1 << (long) nextLoop;
+            nextLoop++;
+        }
+        assert Long.bitCount(block.loops) == 1;
+    }
+
+    /**
+     * Depth-first traversal of the control flow graph. The flag {@linkplain Block#visited} is used to
+     * visit every block only once. The flag {@linkplain Block#active} is used to detect cycles (backward
+     * edges).
+     */
+    private long computeBlockOrder(Block block) {
+        if (block.visited) {
+            if (block.active) {
+                // Reached block via backward branch.
+                makeLoopHeader(block);
+            }
+            // Return cached loop information for this block.
+            return block.loops;
+        }
+
+        block.visited = true;
+        block.active = true;
+
+        int loops = 0;
+        for (Block successor : block.successors) {
+            // Recursively process successors.
+            loops |= computeBlockOrder(successor);
+        }
+
+        if (loops != 0) {
+            processLoopBlock(block);
+        }
+        if (block.isLoopHeader) {
+            assert Long.bitCount(block.loops) == 1;
+            loops &= ~block.loops;
+        }
+
+        block.loops = loops;
+        block.active = false;
+        blocks.add(block);
+
+        return loops;
+    }
+
+    private void processLoopBlock(Block block) {
+        // process all the stores in this block
+        byte[] code = method.code();
+        int bci = block.startBci;
+        if (bci >= 0) {
+            while (bci <= block.endBci) {
+                int opcode = Bytes.beU1(code, bci);
+                if (isStore(opcode)) {
+                    processStore(opcode, Bytes.beU1(code, bci + 1));
+
+                } else if (opcode == WIDE) {
+                    opcode = Bytes.beU1(code, bci + 1);
+                    if (isStore(opcode)) {
+                        processStore(opcode, Bytes.beU2(code, bci + 2));
+                    }
+                }
+                bci += lengthOf(code, bci);
+            }
+        }
+    }
+
+    private void processStore(int opcode, int local) {
+        switch (opcode) {
+            case IINC:
+            case ISTORE:
+            case FSTORE:
+            case WSTORE:
+            case ASTORE:
+                storesInLoops.set(local);
+                break;
+
+            case LSTORE:
+            case DSTORE:
+                storesInLoops.set(local);
+                storesInLoops.set(local + 1);
+                break;
+
+            case ISTORE_0:
+            case FSTORE_0:
+            case ASTORE_0:
+            case WSTORE_0:
+                storesInLoops.set(0);
+                break;
+            case ISTORE_1:
+            case FSTORE_1:
+            case ASTORE_1:
+            case WSTORE_1:
+                storesInLoops.set(1);
+                break;
+            case ISTORE_2:
+            case FSTORE_2:
+            case ASTORE_2:
+            case WSTORE_2:
+                storesInLoops.set(2);
+                break;
+            case ISTORE_3:
+            case FSTORE_3:
+            case ASTORE_3:
+            case WSTORE_3:
+                storesInLoops.set(3);
+                break;
+
+            case LSTORE_0:
+            case DSTORE_0:
+                storesInLoops.set(0);
+                storesInLoops.set(1);
+                break;
+            case LSTORE_1:
+            case DSTORE_1:
+                storesInLoops.set(1);
+                storesInLoops.set(2);
+                break;
+            case LSTORE_2:
+            case DSTORE_2:
+                storesInLoops.set(2);
+                storesInLoops.set(3);
+                break;
+            case LSTORE_3:
+            case DSTORE_3:
+                storesInLoops.set(3);
+                storesInLoops.set(4);
+                break;
+
+            default:
+                throw new InternalError("undefined store bytecode");
+        }
+    }
+
+
+
+    /**
+     * Print block information in the format required by {@linkplain CFGPrinter}. The method must
+     * be here because it accesses private state of a block.
+     */
+    public void printBlock(Block block, LogStream out) {
+        out.print("name \"B").print(block.startBci).println('"');
+        out.print("from_bci ").println(block.startBci);
+        out.print("to_bci ").println(block.endBci);
+
+        out.println("predecessors ");
+
+        out.print("successors ");
+        for (Block succ : block.successors) {
+            if (!succ.isExceptionEntry) {
+                out.print("\"B").print(succ.startBci).print("\" ");
+            }
+        }
+        out.println();
+
+        out.print("xhandlers");
+        for (Block succ : block.successors) {
+            if (succ.isExceptionEntry) {
+                out.print("\"B").print(succ.startBci).print("\" ");
+            }
+        }
+        out.println();
+
+        out.print("flags ");
+        if (block.isExceptionEntry) {
+            out.print("\"ex\" ");
+        }
+        if (block.isLoopHeader) {
+            out.print("\"plh\" ");
+        }
+        out.println();
+
+        out.print("loop_depth ").println(Long.bitCount(block.loops));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/CompilerGraph.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,67 @@
+/*
+ * 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.max.graal.compiler.graph;
+
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+
+public class CompilerGraph extends Graph {
+
+    private RiRuntime runtime;
+    private Return returnSingleton;
+    private Unwind unwindSingleton;
+    private CiAssumptions assumptions = new CiAssumptions();
+
+    public CompilerGraph(RiRuntime runtime) {
+        this.runtime = runtime;
+    }
+
+    public void setReturn(Return returnNode) {
+        assert returnSingleton == null;
+        returnSingleton = returnNode;
+    }
+
+    public Return getReturn() {
+        return returnSingleton;
+    }
+
+    public void setUnwind(Unwind unwind) {
+        assert unwindSingleton == null;
+        unwindSingleton = unwind;
+    }
+
+    public Unwind getUnwind() {
+        return unwindSingleton;
+    }
+
+    public RiRuntime runtime() {
+        return runtime;
+    }
+
+    public CiAssumptions assumptions() {
+        return assumptions;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.graph;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.lir.*;
+import com.oracle.max.graal.compiler.observer.*;
+import com.oracle.max.graal.compiler.phases.*;
+import com.oracle.max.graal.compiler.schedule.*;
+import com.oracle.max.graal.compiler.value.*;
+import com.oracle.max.graal.extensions.*;
+import com.oracle.max.graal.graph.*;
+
+/**
+ * This class implements the overall container for the HIR (high-level IR) graph
+ * and directs its construction, optimization, and finalization.
+ */
+public class IR {
+
+    /**
+     * The compilation associated with this IR.
+     */
+    public final GraalCompilation compilation;
+
+    /**
+     * The start block of this IR.
+     */
+    public LIRBlock startBlock;
+
+    /**
+     * The linear-scan ordered list of blocks.
+     */
+    private List<LIRBlock> linearScanOrder;
+
+    /**
+     * The order in which the code is emitted.
+     */
+    private List<LIRBlock> codeEmittingOrder;
+
+    /**
+     * Creates a new IR instance for the specified compilation.
+     * @param compilation the compilation
+     */
+    public IR(GraalCompilation compilation) {
+        this.compilation = compilation;
+    }
+
+    public Map<Node, LIRBlock> valueToBlock;
+
+    /**
+     * Builds the graph, optimizes it, and computes the linear scan block order.
+     */
+    public void build() {
+
+//        Object stored = GraphBuilderPhase.cachedGraphs.get(compilation.method);
+//        if (stored != null) {
+//            Map<Node, Node> replacements = new HashMap<Node, Node>();
+//            CompilerGraph duplicate = (CompilerGraph) stored;
+//            replacements.put(duplicate.start(), compilation.graph.start());
+//            compilation.graph.addDuplicate(duplicate.getNodes(), replacements);
+//        } else {
+            new GraphBuilderPhase(compilation, compilation.method, false).apply(compilation.graph);
+//        }
+
+        Graph graph = compilation.graph;
+
+        if (GraalOptions.TestGraphDuplication) {
+            new DuplicationPhase().apply(graph);
+        }
+
+        new DeadCodeEliminationPhase().apply(graph);
+
+        if (GraalOptions.ProbabilityAnalysis) {
+            new ComputeProbabilityPhase().apply(graph);
+        }
+
+        if (GraalOptions.Inline) {
+            new InliningPhase(compilation, this, null).apply(graph);
+        }
+
+
+        if (GraalOptions.OptCanonicalizer) {
+            new CanonicalizerPhase().apply(graph);
+            new DeadCodeEliminationPhase().apply(graph);
+        }
+
+        if (GraalOptions.Extend) {
+            extensionOptimizations(graph);
+        }
+
+        if (GraalOptions.OptLoops) {
+            graph.mark();
+            new LoopPhase().apply(graph);
+            if (GraalOptions.OptCanonicalizer) {
+                new CanonicalizerPhase(true).apply(graph);
+                new DeadCodeEliminationPhase().apply(graph);
+            }
+        }
+
+        if (GraalOptions.EscapeAnalysis) {
+            new EscapeAnalysisPhase(compilation, this).apply(graph);
+            new CanonicalizerPhase().apply(graph);
+            new DeadCodeEliminationPhase().apply(graph);
+        }
+
+        if (GraalOptions.OptGVN) {
+            graph.recordModifications(EdgeType.USAGES); // GVN 'ideals' will get new usages
+            new GlobalValueNumberingPhase().apply(graph);
+            if (GraalOptions.Rematerialize) {
+                //new Rematerialization2Phase().apply(graph);
+                new RematerializationPhase().apply(graph);
+            }
+            graph.stopRecordModifications();
+        }
+
+        new LoweringPhase(compilation.runtime).apply(graph);
+        if (GraalOptions.Lower) {
+            new MemoryPhase().apply(graph);
+            if (GraalOptions.OptGVN) {
+                graph.recordModifications(EdgeType.USAGES);
+                new GlobalValueNumberingPhase().apply(graph);
+                if (GraalOptions.Rematerialize) {
+                    new RematerializationPhase().apply(graph);
+                }
+                graph.stopRecordModifications();
+            }
+            if (GraalOptions.OptReadElimination) {
+                new ReadEliminationPhase().apply(graph);
+            }
+        }
+
+        IdentifyBlocksPhase schedule = new IdentifyBlocksPhase(true);
+        schedule.apply(graph);
+        compilation.stats.loopCount = schedule.loopCount();
+
+
+        List<Block> blocks = schedule.getBlocks();
+        List<LIRBlock> lirBlocks = new ArrayList<LIRBlock>();
+        Map<Block, LIRBlock> map = new HashMap<Block, LIRBlock>();
+        for (Block b : blocks) {
+            LIRBlock block = new LIRBlock(b.blockID());
+            map.put(b, block);
+            block.setInstructions(b.getInstructions());
+            block.setLinearScanNumber(b.blockID());
+            block.setLoopDepth(b.loopDepth());
+            block.setLoopIndex(b.loopIndex());
+
+            if (b.isLoopEnd()) {
+                block.setLinearScanLoopEnd();
+            }
+
+            if (b.isLoopHeader()) {
+                block.setLinearScanLoopHeader();
+            }
+
+            block.setFirstInstruction(b.firstNode());
+            block.setLastInstruction(b.lastNode());
+            lirBlocks.add(block);
+        }
+
+        for (Block b : blocks) {
+            for (Block succ : b.getSuccessors()) {
+                map.get(b).blockSuccessors().add(map.get(succ));
+            }
+
+            for (Block pred : b.getPredecessors()) {
+                map.get(b).blockPredecessors().add(map.get(pred));
+            }
+        }
+
+        valueToBlock = new HashMap<Node, LIRBlock>();
+        for (LIRBlock b : lirBlocks) {
+            for (Node i : b.getInstructions()) {
+                valueToBlock.put(i, b);
+            }
+        }
+        startBlock = valueToBlock.get(graph.start());
+        assert startBlock != null;
+        assert startBlock.blockPredecessors().size() == 0;
+
+
+        if (GraalOptions.Time) {
+            GraalTimers.COMPUTE_LINEAR_SCAN_ORDER.start();
+        }
+
+        ComputeLinearScanOrder clso = new ComputeLinearScanOrder(lirBlocks.size(), compilation.stats.loopCount, startBlock);
+        linearScanOrder = clso.linearScanOrder();
+        codeEmittingOrder = clso.codeEmittingOrder();
+
+        int z = 0;
+        for (LIRBlock b : linearScanOrder) {
+            b.setLinearScanNumber(z++);
+        }
+
+        printGraph("After linear scan order", compilation.graph);
+
+        if (GraalOptions.Time) {
+            GraalTimers.COMPUTE_LINEAR_SCAN_ORDER.stop();
+        }
+
+    }
+
+
+
+    public static ThreadLocal<ServiceLoader<Optimizer>> optimizerLoader = new ThreadLocal<ServiceLoader<Optimizer>>();
+
+    private void extensionOptimizations(Graph graph) {
+
+        ServiceLoader<Optimizer> serviceLoader = optimizerLoader.get();
+        if (serviceLoader == null) {
+            serviceLoader = ServiceLoader.load(Optimizer.class);
+            optimizerLoader.set(serviceLoader);
+        }
+
+        for (Optimizer o : serviceLoader) {
+            o.optimize(compilation.runtime, graph);
+        }
+    }
+
+    /**
+     * Gets the linear scan ordering of blocks as a list.
+     * @return the blocks in linear scan order
+     */
+    public List<LIRBlock> linearScanOrder() {
+        return linearScanOrder;
+    }
+
+    public List<LIRBlock> codeEmittingOrder() {
+        return codeEmittingOrder;
+    }
+
+    public void printGraph(String phase, Graph graph) {
+        if (compilation.compiler.isObserved()) {
+            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, phase, graph, true, false));
+        }
+    }
+
+    public int numLoops() {
+        return compilation.stats.loopCount;
+    }
+
+    /**
+     * Gets the maximum number of locks in the graph's frame states.
+     */
+    public final int maxLocks() {
+        int maxLocks = 0;
+        for (Node node : compilation.graph.getNodes()) {
+            if (node instanceof FrameState) {
+                FrameState current = (FrameState) node;
+                int lockCount = 0;
+                while (current != null) {
+                    lockCount += current.locksSize();
+                    current = current.outerFrameState();
+                }
+                if (lockCount > maxLocks) {
+                    maxLocks = lockCount;
+                }
+            }
+        }
+        return maxLocks;
+    }
+
+    public FixedNodeWithNext getHIRStartBlock() {
+        return (FixedNodeWithNext) compilation.graph.start().successors().get(0);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/JSRNotSupportedBailout.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.graph;
+
+import com.sun.cri.ci.*;
+
+
+public class JSRNotSupportedBailout extends CiBailout{
+    private static final long serialVersionUID = -7476925652727154272L;
+
+    public JSRNotSupportedBailout() {
+        super("jsr/ret not supported");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/MergeableState.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.graph;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.ir.*;
+
+public interface MergeableState <T> {
+    T clone();
+    boolean merge(Merge merge, Collection<T> withStates);
+    void loopBegin(LoopBegin loopBegin);
+    void loopEnd(LoopEnd loopEnd, T loopEndState);
+    void afterSplit(FixedNode node);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/PostOrderNodeIterator.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.graph;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.graph.*;
+
+public abstract class PostOrderNodeIterator<T extends MergeableState<T>> {
+
+    private final NodeBitMap visitedEnds;
+    private final Deque<FixedNode> nodeQueue;
+    private final HashMap<FixedNode, T> nodeStates;
+    private final FixedNode start;
+
+    protected T state;
+
+    public PostOrderNodeIterator(FixedNode start, T initialState) {
+        visitedEnds = start.graph().createNodeBitMap();
+        nodeQueue = new ArrayDeque<FixedNode>();
+        nodeStates = new HashMap<FixedNode, T>();
+        this.start = start;
+        this.state = initialState;
+    }
+
+    public void apply() {
+        FixedNode current = start;
+
+        do {
+            if (current instanceof Invoke) {
+                invoke((Invoke) current);
+                queueSuccessors(current);
+                current = nextQueuedNode();
+            } else if (current instanceof LoopBegin) {
+                state.loopBegin((LoopBegin) current);
+                nodeStates.put(current, state);
+                state = state.clone();
+                loopBegin((LoopBegin) current);
+                current = ((LoopBegin) current).next();
+                assert current != null;
+            } else if (current instanceof LoopEnd) {
+                T loopBeginState = nodeStates.get(((LoopEnd) current).loopBegin());
+                if (loopBeginState != null) {
+                    loopBeginState.loopEnd((LoopEnd) current, state);
+                }
+                loopEnd((LoopEnd) current);
+                current = nextQueuedNode();
+            } else if (current instanceof Merge) {
+                merge((Merge) current);
+                current = ((Merge) current).next();
+                assert current != null;
+            } else if (current instanceof FixedNodeWithNext) {
+                FixedNode next = ((FixedNodeWithNext) current).next();
+                node(current);
+                current = next;
+                assert current != null;
+            } else if (current instanceof EndNode) {
+                end((EndNode) current);
+                queueMerge((EndNode) current);
+                current = nextQueuedNode();
+            } else if (current instanceof Deoptimize) {
+                deoptimize((Deoptimize) current);
+                current = nextQueuedNode();
+            } else if (current instanceof Return) {
+                returnNode((Return) current);
+                current = nextQueuedNode();
+            } else if (current instanceof Unwind) {
+                unwind((Unwind) current);
+                current = nextQueuedNode();
+            } else if (current instanceof ControlSplit) {
+                controlSplit((ControlSplit) current);
+                queueSuccessors(current);
+                current = nextQueuedNode();
+            } else {
+                assert false : current.shortName();
+            }
+        } while(current != null);
+    }
+
+    private void queueSuccessors(FixedNode x) {
+        nodeStates.put(x, state);
+        for (Node node : x.successors()) {
+            if (node != null) {
+                nodeQueue.addFirst((FixedNode) node);
+            }
+        }
+    }
+
+    private FixedNode nextQueuedNode() {
+        int maxIterations = nodeQueue.size();
+        while (maxIterations-- > 0) {
+            FixedNode node = nodeQueue.removeFirst();
+            if (node instanceof Merge) {
+                Merge merge = (Merge) node;
+                state = nodeStates.get(merge.endAt(0)).clone();
+                ArrayList<T> states = new ArrayList<T>(merge.endCount() - 1);
+                for (int i = 1; i < merge.endCount(); i++) {
+                    T other = nodeStates.get(merge.endAt(i));
+                    assert other != null;
+                    states.add(other);
+                }
+                boolean ready = state.merge(merge, states);
+                if (ready) {
+                    return merge;
+                } else {
+                    nodeQueue.addLast(merge);
+                }
+            } else {
+                assert node.predecessors().size() == 1;
+                state = nodeStates.get(node.predecessors().get(0)).clone();
+                state.afterSplit(node);
+                return node;
+            }
+        }
+        return null;
+    }
+
+    private void queueMerge(EndNode end) {
+        assert !visitedEnds.isMarked(end);
+        assert !nodeStates.containsKey(end);
+        nodeStates.put(end, state);
+        visitedEnds.mark(end);
+        Merge merge = end.merge();
+        boolean endsVisited = true;
+        for (int i = 0; i < merge.endCount(); i++) {
+            if (!visitedEnds.isMarked(merge.endAt(i))) {
+                endsVisited = false;
+                break;
+            }
+        }
+        if (endsVisited) {
+            nodeQueue.add(merge);
+        }
+    }
+
+    protected abstract void node(FixedNode node);
+
+    protected void end(EndNode endNode) {
+        node(endNode);
+    }
+
+    protected void merge(Merge merge) {
+        node(merge);
+    }
+
+    protected void loopBegin(LoopBegin loopBegin) {
+        node(loopBegin);
+    }
+
+    protected void loopEnd(LoopEnd loopEnd) {
+        node(loopEnd);
+    }
+
+    protected void deoptimize(Deoptimize deoptimize) {
+        node(deoptimize);
+    }
+
+    protected void controlSplit(ControlSplit controlSplit) {
+        node(controlSplit);
+    }
+
+    protected void returnNode(Return returnNode) {
+        node(returnNode);
+    }
+
+    protected void invoke(Invoke invoke) {
+        node(invoke);
+    }
+
+    protected void unwind(Unwind unwind) {
+        node(unwind);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/package-info.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+/**
+ * <H2>IR Graph building</H2>
+ *
+ * The {@link com.oracle.max.graal.compiler.graph.IR} class drives the generation of the HIR graph for a method, making use of other
+ * utility classes in this package.
+ *
+ */
+package com.oracle.max.graal.compiler.graph;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AbstractMemoryCheckpointNode.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,54 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public abstract class AbstractMemoryCheckpointNode extends StateSplit {
+
+    private static final int SUCCESSOR_COUNT = 0;
+    private static final int INPUT_COUNT = 0;
+
+    public AbstractMemoryCheckpointNode(Graph graph) {
+        this(CiKind.Illegal, 0, 0, graph);
+    }
+
+    public AbstractMemoryCheckpointNode(CiKind result, int inputCount, int successorCount, Graph graph) {
+        super(result, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+    }
+
+    @Override
+    public Map<Object, Object> getDebugProperties() {
+        Map<Object, Object> debugProperties = super.getDebugProperties();
+        debugProperties.put("memoryCheckpoint", "true");
+        return debugProperties;
+    }
+
+    public List<Node> mergedNodes() {
+        return variableInputs();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AbstractVectorNode.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,94 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public abstract class AbstractVectorNode extends StateSplit {
+
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_VECTOR = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    public void setVector(AbstractVectorNode length) {
+        inputs().set(super.inputCount() + INPUT_VECTOR, length);
+    }
+
+    public AbstractVectorNode vector() {
+        return (AbstractVectorNode) inputs().get(super.inputCount() + INPUT_VECTOR);
+    }
+
+    public AbstractVectorNode(CiKind kind, int inputCount, int successorCount, AbstractVectorNode vector, Graph graph) {
+        super(kind, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+        setVector(vector);
+    }
+
+    protected static AbstractVectorNode findCommonNode(AbstractVectorNode left, AbstractVectorNode right, List<AbstractVectorNode> leftList, List<AbstractVectorNode> rightList) {
+        Set<AbstractVectorNode> occured = new HashSet<AbstractVectorNode>();
+        AbstractVectorNode common = null;
+        AbstractVectorNode cur = left;
+        while (cur != null) {
+            occured.add(cur);
+            cur = cur.vector();
+        }
+
+        cur = right;
+        while (cur != null) {
+            if (occured.contains(cur)) {
+                common = cur;
+                break;
+            }
+            cur = cur.vector();
+        }
+
+        fillUntil(left, cur, leftList);
+        fillUntil(right, cur, rightList);
+        return common;
+    }
+
+    private static void fillUntil(AbstractVectorNode left, AbstractVectorNode until, List<AbstractVectorNode> leftList) {
+        AbstractVectorNode cur = left;
+        while (cur != null && cur != until) {
+            leftList.add(cur);
+            cur = cur.vector();
+        }
+    }
+
+    public void addToLoop(LoopBegin loop, IdentityHashMap<AbstractVectorNode, Value> nodes) {
+        throw new IllegalStateException("unimplemented");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessArray.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+/**
+ * This the base class of all array operations.
+ */
+public abstract class AccessArray extends StateSplit {
+
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_ARRAY = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The instruction that produces the array object.
+     */
+     public Value array() {
+        return (Value) inputs().get(super.inputCount() + INPUT_ARRAY);
+    }
+
+    public Value setArray(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_ARRAY, n);
+    }
+
+    /**
+     * Creates a new AccessArray instruction.
+     * @param kind the type of the result of this instruction
+     * @param array the instruction that produces the array object value
+     * @param inputCount
+     * @param successorCount
+     * @param graph
+     */
+    public AccessArray(CiKind kind, Value array, int inputCount, int successorCount, Graph graph) {
+        super(kind, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+        setArray(array);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessField.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The base class of all instructions that access fields.
+ */
+public abstract class AccessField extends StateSplit {
+
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_OBJECT = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The instruction that produces the receiver object of this field access (for instance field accesses).
+     */
+     public Value object() {
+        return (Value) inputs().get(super.inputCount() + INPUT_OBJECT);
+    }
+
+    public Value setObject(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_OBJECT, n);
+    }
+
+    protected final RiField field;
+
+    /**
+     * Constructs a new access field object.
+     * @param kind the result kind of the access
+     * @param object the instruction producing the receiver object
+     * @param field the compiler interface representation of the field
+     * @param inputCount
+     * @param successorCount
+     * @param graph
+     */
+    public AccessField(CiKind kind, Value object, RiField field, int inputCount, int successorCount, Graph graph) {
+        super(kind, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+        this.field = field;
+        setObject(object);
+        assert field.isResolved();
+        assert field.holder().isInitialized();
+    }
+
+    /**
+     * Gets the compiler interface field for this field access.
+     * @return the compiler interface field for this field access
+     */
+    public RiField field() {
+        return field;
+    }
+
+    /**
+     * Checks whether this field access is an access to a static field.
+     * @return {@code true} if this field access is to a static field
+     */
+    public boolean isStatic() {
+        return Modifier.isStatic(field.accessFlags());
+    }
+
+    /**
+     * Checks whether this field is declared volatile.
+     * @return {@code true} if the field is resolved and declared volatile
+     */
+    public boolean isVolatile() {
+        return Modifier.isVolatile(field.accessFlags());
+    }
+
+    @Override
+    public Map<Object, Object> getDebugProperties() {
+        Map<Object, Object> properties = super.getDebugProperties();
+        properties.put("field", field);
+        return properties;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessIndexed.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code AccessIndexed} class is the base class of instructions that read or write
+ * elements of an array.
+ */
+public abstract class AccessIndexed extends AccessArray {
+
+    private static final int INPUT_COUNT = 2;
+    private static final int INPUT_INDEX = 0;
+    private static final int INPUT_LENGTH = 1;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The instruction producing the index into the array.
+     */
+     public Value index() {
+        return (Value) inputs().get(super.inputCount() + INPUT_INDEX);
+    }
+
+    public Value setIndex(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_INDEX, n);
+    }
+
+    /**
+     * The instruction that produces the length of the array.
+     */
+    public Value length() {
+        return (Value) inputs().get(super.inputCount() + INPUT_LENGTH);
+    }
+
+    public Value setLength(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_LENGTH, n);
+    }
+
+    private final CiKind elementType;
+
+    /**
+     * Create an new AccessIndexed instruction.
+     * @param kind the result kind of the access
+     * @param array the instruction producing the array
+     * @param index the instruction producing the index
+     * @param length the instruction producing the length (used in bounds check elimination?)
+     * @param elementKind the type of the elements of the array
+     * @param inputCount
+     * @param successorCount
+     * @param graph
+     */
+    AccessIndexed(CiKind kind, Value array, Value index, Value length, CiKind elementKind, int inputCount, int successorCount, Graph graph) {
+        super(kind, array, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+        setIndex(index);
+        setLength(length);
+        this.elementType = elementKind;
+    }
+
+    /**
+     * Gets the element type of the array.
+     * @return the element type
+     */
+    public CiKind elementKind() {
+        return elementType;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessMonitor.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code AccessMonitor} instruction is the base class of both monitor acquisition and release.
+ */
+public abstract class AccessMonitor extends AbstractMemoryCheckpointNode {
+
+    private static final int INPUT_COUNT = 2;
+    private static final int INPUT_OBJECT = 0;
+    private static final int INPUT_LOCK_ADDRESS = 1;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The instruction producing the object locked or unlocked by this instruction.
+     */
+     public Value object() {
+        return (Value) inputs().get(super.inputCount() + INPUT_OBJECT);
+    }
+
+    public Value setObject(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_OBJECT, n);
+    }
+
+    /**
+     * The instruction producing the address of the lock object.
+     */
+    public Value lockAddress() {
+        return (Value) inputs().get(super.inputCount() + INPUT_LOCK_ADDRESS);
+    }
+
+    public Value setLockAddress(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_LOCK_ADDRESS, n);
+    }
+
+    /**
+     * The lock number of this monitor access.
+     */
+    public final int lockNumber;
+
+    /**
+     * Creates a new AccessMonitor instruction.
+     *
+     * @param object the instruction producing the object
+     * @param lockAddress the address of the on-stack lock object or {@code null} if the runtime does not place locks on the stack
+     * @param lockNumber the number of the lock being acquired
+     * @param inputCount
+     * @param successorCount
+     * @param graph
+     */
+    public AccessMonitor(Value object, Value lockAddress, int lockNumber, int inputCount, int successorCount, Graph graph) {
+        super(CiKind.Illegal, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+        this.lockNumber = lockNumber;
+        setObject(object);
+        setLockAddress(lockAddress);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessNode.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public abstract class AccessNode extends AbstractMemoryCheckpointNode {
+    private static final int INPUT_COUNT = 3;
+    private static final int INPUT_NODE = 0;
+    private static final int INPUT_LOCATION = 1;
+    private static final int INPUT_GUARD = 2;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    private LocationNode location;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    public Value object() {
+        return (Value) inputs().get(super.inputCount() + INPUT_NODE);
+    }
+
+    public Value setObject(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_NODE, n);
+    }
+
+    public GuardNode guard() {
+        return (GuardNode) inputs().get(super.inputCount() + INPUT_GUARD);
+    }
+
+    public void setGuard(GuardNode n) {
+        inputs().set(super.inputCount() + INPUT_GUARD, n);
+    }
+
+    public LocationNode location() {
+        return (LocationNode) inputs().get(super.inputCount() + INPUT_LOCATION);
+    }
+
+    public void setLocation(LocationNode n) {
+        inputs().set(super.inputCount() + INPUT_LOCATION, n);
+    }
+
+    public AccessNode(CiKind kind, Value object, LocationNode location, int inputCount, int successorCount, Graph graph) {
+        super(kind, INPUT_COUNT + inputCount, SUCCESSOR_COUNT + successorCount, graph);
+        setLocation(location);
+        setObject(object);
+    }
+
+    public void addDependency(Node x) {
+        variableInputs().add(x);
+    }
+
+    public List<Node> dependencies() {
+        return variableInputs();
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("mem read from ").print(object());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessVectorNode.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,66 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public abstract class AccessVectorNode extends AbstractVectorNode {
+    private static final int INPUT_COUNT = 2;
+    private static final int INPUT_OBJECT = 0;
+    private static final int INPUT_LOCATION = 1;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    public void setObject(Value object) {
+        inputs().set(super.inputCount() + INPUT_OBJECT, object);
+    }
+
+    public Value object() {
+        return (Value) inputs().get(super.inputCount() + INPUT_OBJECT);
+    }
+
+    public void setLocation(LocationNode object) {
+        inputs().set(super.inputCount() + INPUT_LOCATION, object);
+    }
+
+    public LocationNode location() {
+        return (LocationNode) inputs().get(super.inputCount() + INPUT_LOCATION);
+    }
+
+    public AccessVectorNode(CiKind kind, int inputCount, int successorCount, AbstractVectorNode vector, Value object, LocationNode location, Graph graph) {
+        super(kind, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, vector, graph);
+        setObject(object);
+        setLocation(location);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Anchor.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code Anchor} instruction represents the end of a block with an unconditional jump to another block.
+ */
+public final class Anchor extends FixedNodeWithNext {
+
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    /**
+     * Constructs a new Anchor instruction.
+     * @param graph
+     */
+    public Anchor(Graph graph) {
+        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+    }
+
+    public void addGuard(GuardNode x) {
+        variableInputs().add(x);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitAnchor(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("anchor ").print(next());
+    }
+
+    public Iterable<GuardNode> happensAfterGuards() {
+        final Iterator<Node> usages = this.usages().iterator();
+        return new Iterable<GuardNode>() {
+            public Iterator<GuardNode> iterator() {
+                return new Iterator<GuardNode>() {
+                    private GuardNode next;
+                    @Override
+                    public boolean hasNext() {
+                        if (next == null) {
+                            while (usages.hasNext()) {
+                                Node cur = usages.next();
+                                if (cur instanceof GuardNode) {
+                                    next = ((GuardNode) cur);
+                                    break;
+                                }
+                            }
+                        }
+                        return next != null;
+                    }
+
+                    @Override
+                    public GuardNode next() {
+                        GuardNode result = next;
+                        next = null;
+                        return result;
+                    }
+
+                    @Override
+                    public void remove() {
+                        throw new IllegalStateException();
+                    }
+                };
+            }
+        };
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        Anchor x = new Anchor(into);
+        super.copyInto(x);
+        return x;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/And.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,111 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+public final class And extends Logic {
+    private static final AndCanonicalizerOp CANONICALIZER = new AndCanonicalizerOp();
+
+    /**
+     * @param opcode
+     * @param x
+     * @param y
+     * @param graph
+     */
+    public And(CiKind kind, Value x, Value y, Graph graph) {
+        super(kind, kind == CiKind.Int ? Bytecodes.IAND : Bytecodes.LAND, x, y, graph);
+    }
+
+    @Override
+    public String shortName() {
+        return "&";
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        And x = new And(kind, null, null, into);
+        return x;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static class AndCanonicalizerOp implements CanonicalizerOp {
+        @Override
+        public Node canonical(Node node) {
+            assert node instanceof And;
+            And and = (And) node;
+            CiKind kind = and.kind;
+            Graph graph = and.graph();
+            Value x = and.x();
+            Value y = and.y();
+            if (x == y) {
+                return x;
+            }
+            if (x.isConstant() && !y.isConstant()) {
+                and.swapOperands();
+                Value t = y;
+                y = x;
+                x = t;
+            }
+            if (x.isConstant()) {
+                if (kind == CiKind.Int) {
+                    return Constant.forInt(x.asConstant().asInt() & y.asConstant().asInt(), graph);
+                } else {
+                    assert kind == CiKind.Long;
+                    return Constant.forLong(x.asConstant().asLong() & y.asConstant().asLong(), graph);
+                }
+            } else if (y.isConstant()) {
+                if (kind == CiKind.Int) {
+                    int c = y.asConstant().asInt();
+                    if (c == -1) {
+                        return x;
+                    }
+                    if (c == 0) {
+                        return Constant.forInt(0, graph);
+                    }
+                } else {
+                    assert kind == CiKind.Long;
+                    long c = y.asConstant().asLong();
+                    if (c == -1) {
+                        return x;
+                    }
+                    if (c == 0) {
+                        return Constant.forLong(0, graph);
+                    }
+                }
+            }
+            return and;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Arithmetic.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code ArithmeticOp} class represents arithmetic operations such as addition, subtraction, etc.
+ */
+public abstract class Arithmetic extends Binary {
+
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    private final boolean isStrictFP;
+
+    /**
+     * Creates a new arithmetic operation.
+     * @param opcode the bytecode opcode
+     * @param kind the result kind of the operation
+     * @param x the first input instruction
+     * @param y the second input instruction
+     * @param isStrictFP indicates this operation has strict rounding semantics
+     */
+    public Arithmetic(CiKind kind, int opcode, Value x, Value y, boolean isStrictFP, Graph graph) {
+        super(kind, opcode, x, y, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.isStrictFP = isStrictFP;
+    }
+
+    /**
+     * Checks whether this instruction has strict fp semantics.
+     * @return {@code true} if this instruction has strict fp semantics
+     */
+    public boolean isStrictFP() {
+        return isStrictFP;
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitArithmetic(this);
+    }
+
+    public boolean isCommutative() {
+        return Bytecodes.isCommutative(opcode);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(x()).print(' ').print(this.shortName()).print(' ').print(y());
+    }
+
+    @Override
+    public abstract String shortName();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ArrayLength.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.graph.*;
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code ArrayLength} instruction gets the length of an array.
+ */
+public final class ArrayLength extends FloatingNode {
+    private static final ArrayLengthCanonicalizerOp CANONICALIZER = new ArrayLengthCanonicalizerOp();
+
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_ARRAY = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The instruction that produces the array object.
+     */
+     public Value array() {
+        return (Value) inputs().get(super.inputCount() + INPUT_ARRAY);
+    }
+
+    public Value setArray(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_ARRAY, n);
+    }
+
+    /**
+     * Constructs a new ArrayLength instruction.
+     * @param array the instruction producing the array
+     * @param newFrameState the state after executing this instruction
+     */
+    public ArrayLength(Value array, Graph graph) {
+        super(CiKind.Int, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        setArray(array);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitArrayLength(this);
+    }
+
+    @Override
+    public int valueNumber() {
+        return Util.hash1(Bytecodes.ARRAYLENGTH, array());
+    }
+
+    @Override
+    public boolean valueEqual(Node i) {
+        return i instanceof ArrayLength;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(array()).print(".length");
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new ArrayLength(null, into);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static class ArrayLengthCanonicalizerOp implements CanonicalizerOp {
+        @Override
+        public Node canonical(Node node) {
+            ArrayLength arrayLength = (ArrayLength) node;
+            Value array = arrayLength.array();
+            if (array instanceof NewArray) {
+                Value length = ((NewArray) array).length();
+                if (array instanceof NewMultiArray) {
+                    length = ((NewMultiArray) array).dimension(0);
+                }
+                assert length != null;
+                return length;
+            }
+            CiConstant constantValue = null;
+            if (array.isConstant()) {
+                constantValue = array.asConstant();
+            }
+            if (constantValue != null && constantValue.isNonNull()) {
+                Graph graph = node.graph();
+                if (graph instanceof CompilerGraph) {
+                    RiRuntime runtime = ((CompilerGraph) graph).runtime();
+                    return Constant.forInt(runtime.getArrayLength(constantValue), graph);
+                }
+            }
+            return arrayLength;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Binary.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code Op2} class is the base of arithmetic and logic operations with two inputs.
+ */
+public abstract class Binary extends FloatingNode {
+
+    private static final int INPUT_COUNT = 2;
+    private static final int INPUT_X = 0;
+    private static final int INPUT_Y = 1;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The first input to this instruction.
+     */
+     public Value x() {
+        return (Value) inputs().get(super.inputCount() + INPUT_X);
+    }
+
+    public Value setX(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_X, n);
+    }
+
+    /**
+     * The second input to this instruction.
+     */
+    public Value y() {
+        return (Value) inputs().get(super.inputCount() + INPUT_Y);
+    }
+
+    public Value setY(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_Y, n);
+    }
+
+    /**
+     * The opcode of this instruction.
+     */
+    public final int opcode;
+
+    /**
+     * Creates a new Op2 instance.
+     * @param kind the result type of this instruction
+     * @param opcode the bytecode opcode
+     * @param x the first input instruction
+     * @param y the second input instruction
+     */
+    public Binary(CiKind kind, int opcode, Value x, Value y, int inputCount, int successorCount, Graph graph) {
+        super(kind, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+        this.opcode = opcode;
+        setX(x);
+        setY(y);
+    }
+
+    /**
+     * Swaps the operands of this instruction. This is only legal for commutative operations.
+     */
+    public void swapOperands() {
+        assert Bytecodes.isCommutative(opcode);
+        Value t = x();
+        setX(y());
+        setY(t);
+    }
+
+    @Override
+    public int valueNumber() {
+        return Util.hash2(opcode, x(), y());
+    }
+
+    @Override
+    public boolean valueEqual(Node i) {
+        if (i instanceof Binary) {
+            Binary o = (Binary) i;
+            return opcode == o.opcode && x() == o.x() && y() == o.y();
+        }
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/BlockClosure.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.schedule.*;
+
+/**
+ * The {@code BlockClosure} interface represents a closure for iterating over blocks.
+ */
+public interface BlockClosure {
+    void apply(Block block);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/BlockList.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import java.util.*;
+
+/**
+ * The {@code BlockList} class implements a specialized list data structure for representing
+ * the predecessor and successor lists of basic blocks.
+ */
+public class BlockList implements Iterable<Merge> {
+
+    private Merge[] array;
+    private int cursor;
+
+    BlockList(int sizeHint) {
+        if (sizeHint > 0) {
+            array = new Merge[sizeHint];
+        } else {
+            array = new Merge[2];
+        }
+    }
+
+    public void remove(int index) {
+        if (index < 0 || index >= cursor) {
+            throw new IndexOutOfBoundsException();
+        }
+        for (int i = index; i < cursor; i++) {
+            array[i] = array[i + 1];
+        }
+        cursor--;
+    }
+
+    public void remove(Merge block) {
+        int j = 0;
+        for (int i = 0; i < cursor; i++) {
+            if (i != j) {
+                array[j] = array[i];
+            }
+            if (array[i] != block) {
+                j++;
+            }
+        }
+        cursor = j;
+    }
+
+    public void exchange(int index1, int index2) {
+        if (index1 < 0 || index1 >= cursor) {
+            throw new IndexOutOfBoundsException();
+        }
+        if (index2 < 0 || index2 >= cursor) {
+            throw new IndexOutOfBoundsException();
+        }
+        Merge t = array[index2];
+        array[index2] = array[index1];
+        array[index1] = t;
+    }
+
+    public void insert(int index, Merge block) {
+        if (index < 0 || index >= cursor) {
+            throw new IndexOutOfBoundsException();
+        }
+        growOne();
+        for (int i = cursor; i > index; i--) {
+            array[i] = array[i - 1];
+        }
+        array[cursor++] = block;
+    }
+
+    public void append(Merge block) {
+        growOne();
+        array[cursor++] = block;
+    }
+
+    public Merge get(int index) {
+        if (index < 0 || index >= cursor) {
+            throw new IndexOutOfBoundsException();
+        }
+        return array[index];
+    }
+
+    public void replace(Merge oldBlock, Merge newBlock) {
+        for (int i = 0; i < cursor; i++) {
+            if (array[i] == oldBlock) {
+                array[i] = newBlock;
+            }
+        }
+    }
+
+    public boolean checkForSameBlock() {
+        if (cursor == 0) {
+            return true;
+        }
+        Merge b = array[0];
+        for (int i = 1; i < cursor; i++) {
+            if (array[i] != b) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public Iterator<Merge> iterator() {
+        return new Iter();
+    }
+
+    private void growOne() {
+        if (cursor == array.length) {
+            array = Arrays.copyOf(array, array.length * 3);
+        }
+    }
+
+    private class Iter implements Iterator<Merge> {
+        private int pos;
+
+        public boolean hasNext() {
+            return pos < cursor;
+        }
+
+        public Merge next() {
+            return array[pos++];
+        }
+
+        public void remove() {
+            BlockList.this.remove(pos);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/BooleanNode.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,34 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public abstract class BooleanNode extends FloatingNode {
+
+    public BooleanNode(CiKind kind, int inputCount, int successorCount, Graph graph) {
+        super(kind, inputCount, successorCount, graph);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CastNode.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class CastNode extends FloatingNode {
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_NODE = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    /**
+     * The instruction that produces the object tested against null.
+     */
+    public Value value() {
+        return (Value) inputs().get(super.inputCount() + INPUT_NODE);
+    }
+
+    public void setValue(Value n) {
+        inputs().set(super.inputCount() + INPUT_NODE, n);
+    }
+
+    public CastNode(CiKind kind, Value n, Graph graph) {
+        super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        setValue(n);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+    }
+
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return (T) new LIRGenerator.LIRGeneratorOp() {
+                @Override
+                public void generate(Node n, LIRGenerator generator) {
+                    CastNode conv = (CastNode) n;
+                    conv.setOperand(generator.load(conv.value()));
+                }
+            };
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("cast node ").print(value().toString());
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new CastNode(kind, null, into);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CheckCast.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code CheckCast} instruction represents a {@link Bytecodes#CHECKCAST}.
+ */
+public final class CheckCast extends TypeCheck {
+
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    /**
+     * Creates a new CheckCast instruction.
+     * @param targetClass the class being cast to
+     * @param object the instruction producing the object
+     * @param graph
+     */
+    public CheckCast(Value targetClassInstruction, Value object, Graph graph) {
+        super(targetClassInstruction, object, CiKind.Object, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+    }
+
+    /**
+     * Gets the declared type of the result of this instruction.
+     * @return the declared type of the result
+     */
+    @Override
+    public RiType declaredType() {
+        return targetClass();
+    }
+
+    /**
+     * Gets the exact type of the result of this instruction.
+     * @return the exact type of the result
+     */
+    @Override
+    public RiType exactType() {
+        return targetClass().isResolved() ? targetClass().exactType() : null;
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitCheckCast(this);
+    }
+
+//    @Override
+//    public int valueNumber() {
+//        return targetClass().isResolved() ? Util.hash1(Bytecodes.CHECKCAST, object()) : 0;
+//    }
+//
+//    @Override
+//    public boolean valueEqual(Node i) {
+//        return i instanceof CheckCast;
+//    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("checkcast(").
+        print(object()).
+        print(",").
+        print(targetClassInstruction()).
+        print(") ").
+        print(CiUtil.toJavaName(targetClass()));
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new CheckCast(null, null, into);
+    }
+
+    private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() {
+        @Override
+        public Node canonical(Node node) {
+            CheckCast checkCast = (CheckCast) node;
+            Value object = checkCast.object();
+            RiType exactType = object.exactType();
+            if (exactType != null) {
+                return Constant.forBoolean(exactType.isSubtypeOf(checkCast.targetClass()), node.graph());
+            }
+            CiConstant constant = object.asConstant();
+            if (constant != null) {
+                assert constant.kind == CiKind.Object;
+                if (constant.isNull()) {
+                    return Constant.forBoolean(true, node.graph());
+                } else {
+                    // this should never happen - non-null constants are always expected to provide an exactType
+                    assert false;
+                }
+            }
+            return checkCast;
+        }
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Compare.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.graph.*;
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+/* (tw/gd) 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)
+ *
+ * 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 final class Compare extends BooleanNode {
+
+    private static final int INPUT_COUNT = 2;
+    private static final int INPUT_X = 0;
+    private static final int INPUT_Y = 1;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The instruction that produces the first input to this comparison.
+     */
+     public Value x() {
+        return (Value) inputs().get(super.inputCount() + INPUT_X);
+    }
+
+    public Value setX(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_X, n);
+    }
+
+    /**
+     * The instruction that produces the second input to this comparison.
+     */
+    public Value y() {
+        return (Value) inputs().get(super.inputCount() + INPUT_Y);
+    }
+
+    public Value setY(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_Y, n);
+    }
+
+    Condition condition;
+    boolean unorderedIsTrue;
+
+    /**
+     * Constructs a new Compare instruction.
+     * @param x the instruction producing the first input to the instruction
+     * @param condition the condition (comparison operation)
+     * @param y the instruction that produces the second input to this instruction
+     * @param graph
+     */
+    public Compare(Value x, Condition condition, Value y, Graph graph) {
+        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        assert (x == null && y == null) || Util.archKindsEqual(x, y);
+        this.condition = condition;
+        setX(x);
+        setY(y);
+    }
+
+    @Override
+    public boolean valueEqual(Node i) {
+        if (i instanceof Compare) {
+            Compare compare = (Compare) i;
+            return compare.condition == condition && compare.unorderedIsTrue == unorderedIsTrue;
+        }
+        return super.valueEqual(i);
+    }
+
+    /**
+     * Gets the condition (comparison operation) for this instruction.
+     * @return the condition
+     */
+    public Condition condition() {
+        return condition;
+    }
+
+    /**
+     * Checks whether unordered inputs mean true or false.
+     * @return {@code true} if unordered inputs produce true
+     */
+    public boolean unorderedIsTrue() {
+        return unorderedIsTrue;
+    }
+
+    /**
+     * Swaps the operands to this if and mirrors the condition (e.g. > becomes <).
+     * @see Condition#mirror()
+     */
+    public void swapOperands() {
+        condition = condition.mirror();
+        Value t = x();
+        setX(y());
+        setY(t);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("comp ").
+        print(x()).
+        print(' ').
+        print(condition().operator).
+        print(' ').
+        print(y());
+    }
+
+    @Override
+    public String shortName() {
+        return "Comp " + condition.operator;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        Compare x = new Compare(null, condition, null, into);
+        x.unorderedIsTrue = unorderedIsTrue;
+        return x;
+    }
+
+    private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() {
+        @Override
+        public Node canonical(Node node) {
+            Compare compare = (Compare) node;
+            if (compare.x().isConstant() && compare.y().isConstant()) {
+                CiConstant constX = compare.x().asConstant();
+                CiConstant constY = compare.y().asConstant();
+                Boolean result = compare.condition().foldCondition(constX, constY, ((CompilerGraph) node.graph()).runtime());
+                if (result != null) {
+                    if (GraalOptions.TraceCanonicalizer) {
+                        TTY.println("folded condition " + constX + " " + compare.condition() + " " + constY);
+                    }
+                    return Constant.forBoolean(result, compare.graph());
+                } else {
+                    if (GraalOptions.TraceCanonicalizer) {
+                        TTY.println("if not removed %s %s %s (%s %s)", constX, compare.condition(), constY, constX.kind, constY.kind);
+                    }
+                }
+            } else if (compare.x().isConstant() && compare.y() instanceof MaterializeNode) {
+                return optimizeMaterialize(compare, compare.x().asConstant(), (MaterializeNode) compare.y());
+            } else if (compare.y().isConstant() && compare.x() instanceof MaterializeNode) {
+                return optimizeMaterialize(compare, compare.y().asConstant(), (MaterializeNode) compare.x());
+            } else if (compare.x().isConstant() && compare.y() instanceof NormalizeCompare) {
+                return optimizeNormalizeCmp(compare, compare.x().asConstant(), (NormalizeCompare) compare.y());
+            } else if (compare.y().isConstant() && compare.x() instanceof NormalizeCompare) {
+                return optimizeNormalizeCmp(compare, compare.y().asConstant(), (NormalizeCompare) compare.x());
+            }
+            if (compare.x() == compare.y() && compare.x().kind != CiKind.Float && compare.x().kind != CiKind.Double) {
+                return Constant.forBoolean(compare.condition().check(1, 1), compare.graph());
+            }
+            return compare;
+        }
+
+        private Node optimizeMaterialize(Compare compare, CiConstant constant, MaterializeNode materializeNode) {
+            if (constant.kind == CiKind.Int) {
+                boolean isFalseCheck = (constant.asInt() == 0);
+                if (compare.condition == Condition.EQ || compare.condition == Condition.NE) {
+                    if (compare.condition == Condition.NE) {
+                        isFalseCheck = !isFalseCheck;
+                    }
+                    Value result = materializeNode.value();
+                    if (isFalseCheck) {
+                        result = new NegateBooleanNode(result, compare.graph());
+                    }
+                    if (GraalOptions.TraceCanonicalizer) {
+                        TTY.println("Removed materialize replacing with " + result);
+                    }
+                    return result;
+                }
+            }
+            return compare;
+        }
+
+        private Node optimizeNormalizeCmp(Compare compare, CiConstant constant, NormalizeCompare normalizeNode) {
+            if (constant.kind == CiKind.Int && constant.asInt() == 0) {
+                Condition condition = compare.condition();
+                if (normalizeNode == compare.y()) {
+                    condition = condition.mirror();
+                }
+                Compare result = new Compare(normalizeNode.x(), condition, normalizeNode.y(), compare.graph());
+                boolean isLess = condition == Condition.LE || condition == Condition.LT || condition == Condition.BE || condition == Condition.BT;
+                result.unorderedIsTrue = condition != Condition.EQ && (condition == Condition.NE || !(isLess ^ normalizeNode.isUnorderedLess()));
+                if (GraalOptions.TraceCanonicalizer) {
+                    TTY.println("Replaced Compare+NormalizeCompare with " + result);
+                }
+                return result;
+            }
+            return compare;
+        }
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ComputeLinearScanOrder.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,357 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.lir.*;
+import com.oracle.max.graal.graph.*;
+
+public final class ComputeLinearScanOrder {
+
+    private final int maxBlockId; // the highest blockId of a block
+    private int numBlocks; // total number of blocks (smaller than maxBlockId)
+
+    List<LIRBlock> linearScanOrder; // the resulting list of blocks in correct order
+    List<LIRBlock> codeEmittingOrder;
+
+    final BitMap visitedBlocks; // used for recursive processing of blocks
+    final BitMap activeBlocks; // used for recursive processing of blocks
+    final BitMap dominatorBlocks; // temporary BitMap used for computation of dominator
+    final int[] forwardBranches; // number of incoming forward branches for each block
+    final List<LIRBlock> workList; // temporary list (used in markLoops and computeOrder)
+    final LIRBlock[] loopHeaders;
+
+    // accessors for visitedBlocks and activeBlocks
+    void initVisited() {
+        activeBlocks.clearAll();
+        visitedBlocks.clearAll();
+    }
+
+    boolean isVisited(LIRBlock b) {
+        return visitedBlocks.get(b.blockID());
+    }
+
+    boolean isActive(LIRBlock b) {
+        return activeBlocks.get(b.blockID());
+    }
+
+    void setVisited(LIRBlock b) {
+        assert !isVisited(b) : "already set";
+        visitedBlocks.set(b.blockID());
+    }
+
+    void setActive(LIRBlock b) {
+        assert !isActive(b) : "already set";
+        activeBlocks.set(b.blockID());
+    }
+
+    void clearActive(LIRBlock b) {
+        assert isActive(b) : "not already";
+        activeBlocks.clear(b.blockID());
+    }
+
+    // accessors for forwardBranches
+    void incForwardBranches(LIRBlock b) {
+        forwardBranches[b.blockID()]++;
+    }
+
+    int decForwardBranches(LIRBlock b) {
+        return --forwardBranches[b.blockID()];
+    }
+
+    // accessors for final result
+    public List<LIRBlock> linearScanOrder() {
+        return linearScanOrder;
+    }
+
+    public ComputeLinearScanOrder(int maxBlockId, int loopCount, LIRBlock startBlock) {
+        loopHeaders = new LIRBlock[loopCount];
+
+        this.maxBlockId = maxBlockId;
+        visitedBlocks = new BitMap(maxBlockId);
+        activeBlocks = new BitMap(maxBlockId);
+        dominatorBlocks = new BitMap(maxBlockId);
+        forwardBranches = new int[maxBlockId];
+        workList = new ArrayList<LIRBlock>(8);
+
+        countEdges(startBlock, null);
+        computeOrder(startBlock);
+        printBlocks();
+    }
+
+    /**
+     * Traverses the CFG to analyze block and edge info. The analysis performed is:
+     *
+     * 1. Count of total number of blocks.
+     * 2. Count of all incoming edges and backward incoming edges.
+     * 3. Number loop header blocks.
+     * 4. Create a list with all loop end blocks.
+     */
+    void countEdges(LIRBlock cur, LIRBlock parent) {
+        if (GraalOptions.TraceLinearScanLevel >= 3) {
+            TTY.println("Counting edges for block B%d%s", cur.blockID(), parent == null ? "" : " coming from B" + parent.blockID());
+        }
+
+        if (isActive(cur)) {
+            return;
+        }
+
+        // increment number of incoming forward branches
+        incForwardBranches(cur);
+
+        if (isVisited(cur)) {
+            if (GraalOptions.TraceLinearScanLevel >= 3) {
+                TTY.println("block already visited");
+            }
+            return;
+        }
+
+        numBlocks++;
+        setVisited(cur);
+        setActive(cur);
+
+        // recursive call for all successors
+        int i;
+        for (i = cur.numberOfSux() - 1; i >= 0; i--) {
+            countEdges(cur.suxAt(i), cur);
+        }
+
+        clearActive(cur);
+
+        if (GraalOptions.TraceLinearScanLevel >= 3) {
+            TTY.println("Finished counting edges for block B%d", cur.blockID());
+        }
+    }
+
+    int computeWeight(LIRBlock cur) {
+
+        // limit loop-depth to 15 bit (only for security reason, it will never be so big)
+        int weight = (cur.loopDepth() & 0x7FFF) << 16;
+
+        int curBit = 15;
+
+        // this is necessary for the (very rare) case that two successive blocks have
+        // the same loop depth, but a different loop index (can happen for endless loops
+        // with exception handlers)
+//        if (!cur.isLinearScanLoopHeader()) {
+//            weight |= 1 << curBit;
+//        }
+//        curBit--;
+
+        // loop end blocks (blocks that end with a backward branch) are added
+        // after all other blocks of the loop.
+        if (!cur.isLinearScanLoopEnd()) {
+            weight |= 1 << curBit;
+        }
+        curBit--;
+
+        // critical edge split blocks are preferred because then they have a greater
+        // probability to be completely empty
+        //if (cur.isCriticalEdgeSplit()) {
+        //    weight |= 1 << curBit;
+        //}
+        //curBit--;
+
+        // exceptions should not be thrown in normal control flow, so these blocks
+        // are added as late as possible
+//        if (!(cur.end() instanceof Throw) && (singleSux == null || !(singleSux.end() instanceof Throw))) {
+//            weight |= 1 << curBit;
+//        }
+//        curBit--;
+//        if (!(cur.end() instanceof Return) && (singleSux == null || !(singleSux.end() instanceof Return))) {
+//            weight |= 1 << curBit;
+//        }
+//        curBit--;
+
+        // exceptions handlers are added as late as possible
+        if (!cur.isExceptionEntry()) {
+            weight |= 1 << curBit;
+        }
+        curBit--;
+
+        // guarantee that weight is > 0
+        weight |= 1;
+
+        assert curBit >= 0 : "too many flags";
+        assert weight > 0 : "weight cannot become negative";
+
+        return weight;
+    }
+
+    private boolean readyForProcessing(LIRBlock cur) {
+        // Discount the edge just traveled.
+        // When the number drops to zero, all forward branches were processed
+        if (decForwardBranches(cur) != 0) {
+            return false;
+        }
+
+        assert !linearScanOrder.contains(cur) : "block already processed (block can be ready only once)";
+        assert !workList.contains(cur) : "block already in work-list (block can be ready only once)";
+        return true;
+    }
+
+    private void sortIntoWorkList(LIRBlock cur) {
+        assert !workList.contains(cur) : "block already in work list";
+
+        int curWeight = computeWeight(cur);
+
+        // the linearScanNumber is used to cache the weight of a block
+        cur.setLinearScanNumber(curWeight);
+
+        if (GraalOptions.StressLinearScan) {
+            workList.add(0, cur);
+            return;
+        }
+
+        workList.add(null); // provide space for new element
+
+        int insertIdx = workList.size() - 1;
+        while (insertIdx > 0 && workList.get(insertIdx - 1).linearScanNumber() > curWeight) {
+            workList.set(insertIdx, workList.get(insertIdx - 1));
+            insertIdx--;
+        }
+        workList.set(insertIdx, cur);
+
+        if (GraalOptions.TraceLinearScanLevel >= 3) {
+            TTY.println("Sorted B%d into worklist. new worklist:", cur.blockID());
+            for (int i = 0; i < workList.size(); i++) {
+                TTY.println(String.format("%8d B%02d  weight:%6x", i, workList.get(i).blockID(), workList.get(i).linearScanNumber()));
+            }
+        }
+
+        for (int i = 0; i < workList.size(); i++) {
+            assert workList.get(i).linearScanNumber() > 0 : "weight not set";
+            assert i == 0 || workList.get(i - 1).linearScanNumber() <= workList.get(i).linearScanNumber() : "incorrect order in worklist";
+        }
+    }
+
+    private void appendBlock(LIRBlock cur) {
+        if (GraalOptions.TraceLinearScanLevel >= 3) {
+            TTY.println("appending block B%d (weight 0x%06x) to linear-scan order", cur.blockID(), cur.linearScanNumber());
+        }
+        assert !linearScanOrder.contains(cur) : "cannot add the same block twice";
+
+        // currently, the linear scan order and code emit order are equal.
+        // therefore the linearScanNumber and the weight of a block must also
+        // be equal.
+        cur.setLinearScanNumber(linearScanOrder.size());
+        linearScanOrder.add(cur);
+
+        if (!cur.isLinearScanLoopHeader() || !GraalOptions.OptReorderLoops) {
+            codeEmittingOrder.add(cur);
+
+            if (cur.isLinearScanLoopEnd() && GraalOptions.OptReorderLoops) {
+                LIRBlock loopHeader = loopHeaders[cur.loopIndex()];
+                assert loopHeader != null;
+                codeEmittingOrder.add(loopHeader);
+
+                for (LIRBlock succ : loopHeader.blockSuccessors()) {
+                    if (succ.loopDepth() == loopHeader.loopDepth()) {
+                        succ.setAlign(true);
+                    }
+                }
+            }
+        } else {
+            loopHeaders[cur.loopIndex()] = cur;
+        }
+    }
+
+    private void computeOrder(LIRBlock startBlock) {
+        if (GraalOptions.TraceLinearScanLevel >= 3) {
+            TTY.println("----- computing final block order");
+        }
+
+        // the start block is always the first block in the linear scan order
+        linearScanOrder = new ArrayList<LIRBlock>(numBlocks);
+
+        codeEmittingOrder = new ArrayList<LIRBlock>(numBlocks);
+
+        // start processing with standard entry block
+        assert workList.isEmpty() : "list must be empty before processing";
+
+        assert readyForProcessing(startBlock);
+        sortIntoWorkList(startBlock);
+
+        do {
+            LIRBlock cur = workList.remove(workList.size() - 1);
+            appendBlock(cur);
+
+            int i;
+            int numSux = cur.numberOfSux();
+            // changed loop order to get "intuitive" order of if- and else-blocks
+            for (i = 0; i < numSux; i++) {
+                LIRBlock sux = cur.suxAt(i);
+                if (readyForProcessing(sux)) {
+                    sortIntoWorkList(sux);
+                }
+            }
+        } while (workList.size() > 0);
+    }
+
+    public void printBlocks() {
+        if (GraalOptions.TraceLinearScanLevel >= 2) {
+            TTY.println("----- loop information:");
+            for (LIRBlock cur : linearScanOrder) {
+                TTY.print(String.format("%4d: B%02d: ", cur.linearScanNumber(), cur.blockID()));
+                TTY.println(String.format(" . loopIndex: %2d, loopDepth: %2d", cur.loopIndex(), cur.loopDepth()));
+            }
+        }
+
+        if (GraalOptions.TraceLinearScanLevel >= 1) {
+            TTY.println("----- linear-scan block order:");
+            for (LIRBlock cur : linearScanOrder) {
+                TTY.print(String.format("%4d: B%02d    loop: %2d  depth: %2d", cur.linearScanNumber(), cur.blockID(), cur.loopIndex(), cur.loopDepth()));
+
+                TTY.print(cur.isLinearScanLoopHeader() ? " lh" : "   ");
+                TTY.print(cur.isLinearScanLoopEnd() ? " le" : "   ");
+
+                TTY.print("    dom: null ");
+
+
+                if (cur.numberOfPreds() > 0) {
+                    TTY.print("    preds: ");
+                    for (int j = 0; j < cur.numberOfPreds(); j++) {
+                        LIRBlock pred = cur.predAt(j);
+                        TTY.print("B%d ", pred.blockID());
+                    }
+                }
+                if (cur.numberOfSux() > 0) {
+                    TTY.print("    sux: ");
+                    for (int j = 0; j < cur.numberOfSux(); j++) {
+                        LIRBlock sux = cur.suxAt(j);
+                        TTY.print("B%d ", sux.blockID());
+                    }
+                }
+                TTY.println();
+            }
+        }
+    }
+
+    public List<LIRBlock> codeEmittingOrder() {
+        return codeEmittingOrder;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Condition.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * 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("|<|"),
+
+    /**
+     * Operation produced an overflow.
+     */
+    OF("overflow"),
+
+    /**
+     * Operation did not produce an overflow.
+     */
+    NOF("noOverflow"),
+
+    TRUE("TRUE");
+
+    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 BT: return (left & 0xffffffffL) < (right & 0xffffffffL);
+            case BE: return (left & 0xffffffffL) <= (right & 0xffffffffL);
+            case AT: return (left & 0xffffffffL) > (right & 0xffffffffL);
+            case AE: return (left & 0xffffffffL) >= (right & 0xffffffffL);
+        }
+        throw new IllegalArgumentException();
+    }
+
+    /**
+     * 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());
+    }
+
+    /**
+     * 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();
+    }
+
+    /**
+     * 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 runtime the RiRuntime (might be needed to compare runtime-specific types)
+     * @return {@link Boolean#TRUE} if the comparison is known to be true,
+     * {@link Boolean#FALSE} if the comparison is known to be false, {@code null} otherwise.
+     */
+    public Boolean foldCondition(CiConstant lt, CiConstant rt, RiRuntime runtime) {
+        switch (lt.kind) {
+            case Boolean:
+            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 toUnsigned(x) >= toUnsigned(y);
+                    case BE: return toUnsigned(x) <= toUnsigned(y);
+                    case AT: return toUnsigned(x) > toUnsigned(y);
+                    case BT: return toUnsigned(x) < toUnsigned(y);
+                }
+                break;
+            }
+            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;
+                }
+                break;
+            }
+            case Object: {
+                switch (this) {
+                    case EQ: return runtime.areConstantObjectsEqual(lt, rt);
+                    case NE: return !runtime.areConstantObjectsEqual(lt, rt);
+                }
+                break;
+            }
+            // XXX: folding of floating comparisons should be possible
+        }
+        return null;
+    }
+
+    private long toUnsigned(int x) {
+        if (x < 0) {
+            return ((long) (x & 0x7FFFFFFF)) + ((long) Integer.MAX_VALUE) + 1;
+        }
+        return x;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Conditional.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code IfOp} class represents a comparison that yields one of two values.
+ * Note that these nodes are not built directly from the bytecode but are introduced
+ * by conditional expression elimination.
+ */
+public final class Conditional extends Binary {
+
+    private static final int INPUT_COUNT = 2;
+    private static final int INPUT_TRUE_VALUE = 0;
+    private static final int INPUT_FALSE_VALUE = 1;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+
+    /**
+     * The instruction that produces the value if the comparison is true.
+     */
+    public Value trueValue() {
+        return (Value) inputs().get(super.inputCount() + INPUT_TRUE_VALUE);
+    }
+
+    public Value setTrueValue(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_TRUE_VALUE, n);
+    }
+
+    /**
+     * The instruction that produces the value if the comparison is false.
+     */
+    public Value falseValue() {
+        return (Value) inputs().get(super.inputCount() + INPUT_FALSE_VALUE);
+    }
+
+    public Value setFalseValue(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_FALSE_VALUE, n);
+    }
+
+
+    Condition condition;
+
+    /**
+     * Constructs a new IfOp.
+     * @param x the instruction producing the first value to be compared
+     * @param condition the condition of the comparison
+     * @param y the instruction producing the second value to be compared
+     * @param trueValue the value produced if the condition is true
+     * @param falseValue the value produced if the condition is false
+     */
+    public Conditional(Value x, Condition condition, Value y, Value trueValue, Value falseValue, Graph graph) {
+        // TODO: return the appropriate bytecode IF_ICMPEQ, etc
+        super(trueValue.kind.meet(falseValue.kind), Bytecodes.ILLEGAL, x, y, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.condition = condition;
+        setTrueValue(trueValue);
+        setFalseValue(falseValue);
+    }
+
+    // for copying
+    private Conditional(CiKind kind, Condition cond, Graph graph) {
+        super(kind, Bytecodes.ILLEGAL, null, null, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.condition = cond;
+    }
+
+    /**
+     * Gets the condition of this if operation.
+     * @return the condition
+     */
+    public Condition condition() {
+        return condition;
+    }
+
+    /**
+     * Checks whether this comparison operator is commutative (i.e. it is either == or !=).
+     * @return {@code true} if this comparison is commutative
+     */
+    public boolean isCommutative() {
+        return condition == Condition.EQ || condition == Condition.NE;
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitIfOp(this);
+    }
+
+    @Override
+    public int valueNumber() {
+        return Util.hash4(condition.hashCode(), x(), y(), trueValue(), falseValue());
+    }
+
+    @Override
+    public boolean valueEqual(Node i) {
+        if (i instanceof Conditional) {
+            Conditional o = (Conditional) i;
+            return opcode == o.opcode && x() == o.x() && y() == o.y() && trueValue() == o.trueValue() && falseValue() == o.falseValue();
+        }
+        return false;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(x()).
+        print(' ').
+        print(condition().operator).
+        print(' ').
+        print(y()).
+        print(" ? ").
+        print(trueValue()).
+        print(" : ").
+        print(falseValue());
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        Conditional x = new Conditional(kind, condition, into);
+        return x;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Constant.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import static com.oracle.max.graal.compiler.GraalCompilation.*;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code Constant} instruction represents a constant such as an integer value,
+ * long, float, object reference, address, etc.
+ */
+public final class Constant extends BooleanNode {
+
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    public final CiConstant value;
+
+    /**
+     * Constructs a new instruction representing the specified constant.
+     * @param value the constant
+     * @param graph
+     */
+    public Constant(CiConstant value, Graph graph) {
+        super(value.kind.stackKind(), INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.value = value;
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitConstant(this);
+    }
+
+    /**
+     * Creates an instruction for a double constant.
+     * @param d the double value for which to create the instruction
+     * @param graph
+     * @return an instruction representing the double
+     */
+    public static Constant forDouble(double d, Graph graph) {
+        return new Constant(CiConstant.forDouble(d), graph);
+    }
+
+    /**
+     * Creates an instruction for a float constant.
+     * @param f the float value for which to create the instruction
+     * @return an instruction representing the float
+     */
+    public static Constant forFloat(float f, Graph graph) {
+        return new Constant(CiConstant.forFloat(f), graph);
+    }
+
+    /**
+     * Creates an instruction for an long constant.
+     * @param i the long value for which to create the instruction
+     * @return an instruction representing the long
+     */
+    public static Constant forLong(long i, Graph graph) {
+        return new Constant(CiConstant.forLong(i), graph);
+    }
+
+    /**
+     * Creates an instruction for an integer constant.
+     * @param i the integer value for which to create the instruction
+     * @return an instruction representing the integer
+     */
+    public static Constant forInt(int i, Graph graph) {
+        return new Constant(CiConstant.forInt(i), graph);
+    }
+
+    /**
+     * Creates an instruction for a boolean constant.
+     * @param i the boolean value for which to create the instruction
+     * @return an instruction representing the boolean
+     */
+    public static Constant forBoolean(boolean i, Graph graph) {
+        return new Constant(CiConstant.forBoolean(i), graph);
+    }
+
+    /**
+     * Creates an instruction for an address (jsr/ret address) constant.
+     * @param i the address value for which to create the instruction
+     * @return an instruction representing the address
+     */
+    public static Constant forJsr(int i, Graph graph) {
+        return new Constant(CiConstant.forJsr(i), graph);
+    }
+
+    /**
+     * Creates an instruction for an object constant.
+     * @param o the object value for which to create the instruction
+     * @return an instruction representing the object
+     */
+    public static Constant forObject(Object o, Graph graph) {
+        return new Constant(CiConstant.forObject(o), graph);
+    }
+
+    /**
+     * Creates an instruction for a word constant.
+     * @param val the word value for which to create the instruction
+     * @return an instruction representing the word
+     */
+    public static Constant forWord(long val, Graph graph) {
+        return new Constant(CiConstant.forWord(val), graph);
+    }
+
+    public static Constant defaultForKind(CiKind kind, Graph graph) {
+        switch(kind) {
+            case Boolean:
+                return Constant.forBoolean(false, graph);
+            case Byte:
+            case Char:
+            case Short:
+            case Int:
+                return Constant.forInt(0, graph);
+            case Double:
+                return Constant.forDouble(0.0, graph);
+            case Float:
+                return Constant.forFloat(0.0f, graph);
+            case Long:
+                return Constant.forLong(0L, graph);
+            case Object:
+                return Constant.forObject(null, graph);
+            case Word:
+                return Constant.forWord(0L, graph);
+            default:
+                return null;
+        }
+    }
+
+    @Override
+    public String toString() {
+        return super.toString() + "(" + value + ")";
+    }
+
+    @Override
+    public int valueNumber() {
+        return 0x50000000 | value.hashCode();
+    }
+
+    @Override
+    public boolean valueEqual(Node i) {
+        return i instanceof Constant && ((Constant) i).value.equivalent(this.value);
+    }
+
+    @Override
+    public RiType declaredType() {
+        RiRuntime runtime = compilation().runtime;
+        if (kind.isPrimitive()) {
+            return runtime.asRiType(kind);
+        }
+        return runtime.getTypeOf(asConstant());
+    }
+
+    @Override
+    public RiType exactType() {
+        return declaredType();
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(value.valueString());
+    }
+
+    @Override
+    public String shortName() {
+        return value.name();
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new Constant(value, into);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ControlSplit.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code BlockEnd} instruction is a base class for all instructions that end a basic
+ * block, including branches, switches, throws, and goto's.
+ */
+public abstract class ControlSplit extends FixedNode {
+
+    private static final int INPUT_COUNT = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+    private final int blockSuccessorCount;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + blockSuccessorCount + SUCCESSOR_COUNT;
+    }
+
+    public FixedNode blockSuccessor(int index) {
+        assert index >= 0 && index < blockSuccessorCount;
+        return (FixedNode) successors().get(super.successorCount() + SUCCESSOR_COUNT + index);
+    }
+
+    public FixedNode setBlockSuccessor(int index, FixedNode n) {
+        assert index >= 0 && index < blockSuccessorCount;
+        return (FixedNode) successors().set(super.successorCount() + SUCCESSOR_COUNT + index, n);
+    }
+
+    public int blockSuccessorCount() {
+        return blockSuccessorCount;
+    }
+
+    protected final double[] branchProbability;
+
+    /**
+     * Constructs a new block end with the specified value type.
+     * @param kind the type of the value produced by this instruction
+     * @param successors the list of successor blocks. If {@code null}, a new one will be created.
+     */
+    public ControlSplit(CiKind kind, List<? extends FixedNode> blockSuccessors, double[] branchProbability, int inputCount, int successorCount, Graph graph) {
+        this(kind, blockSuccessors.size(), branchProbability, inputCount, successorCount, graph);
+        for (int i = 0; i < blockSuccessors.size(); i++) {
+            setBlockSuccessor(i, blockSuccessors.get(i));
+        }
+    }
+
+    public ControlSplit(CiKind kind, int blockSuccessorCount, double[] branchProbability, int inputCount, int successorCount, Graph graph) {
+        super(kind, inputCount + INPUT_COUNT, successorCount + blockSuccessorCount + SUCCESSOR_COUNT, graph);
+        this.blockSuccessorCount = blockSuccessorCount;
+        assert branchProbability.length == blockSuccessorCount;
+        this.branchProbability = branchProbability;
+    }
+
+    public double probability(int successorIndex) {
+        return branchProbability[successorIndex];
+    }
+
+    public void setProbability(int successorIndex, double x) {
+        branchProbability[successorIndex] = x;
+    }
+
+    /**
+     * Gets the successor corresponding to the default (fall through) case.
+     * @return the default successor
+     */
+    public FixedNode defaultSuccessor() {
+        return blockSuccessor(blockSuccessorCount - 1);
+    }
+
+    public Iterable<FixedNode> blockSuccessors() {
+        return new Iterable<FixedNode>() {
+            @Override
+            public Iterator<FixedNode> iterator() {
+                return new Iterator<FixedNode>() {
+                    int i = 0;
+                    @Override
+                    public void remove() {
+                        throw new UnsupportedOperationException();
+                    }
+                    @Override
+                    public FixedNode next() {
+                        return ControlSplit.this.blockSuccessor(i++);
+                    }
+
+                    @Override
+                    public boolean hasNext() {
+                        return i < ControlSplit.this.blockSuccessorCount;
+                    }
+                };
+            }
+        };
+    }
+
+    @Override
+    public Map<Object, Object> getDebugProperties() {
+        Map<Object, Object> properties = super.getDebugProperties();
+        StringBuilder str = new StringBuilder();
+        for (int i = 0; i < branchProbability.length; i++) {
+            str.append(i == 0 ? "" : ", ").append(String.format("%7.5f", branchProbability[i]));
+        }
+        properties.put("branchProbability", str.toString());
+        return properties;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Convert.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code Convert} class represents a conversion between primitive types.
+ */
+public final class Convert extends FloatingNode {
+
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_VALUE = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The instruction which produces the input value to this instruction.
+     */
+     public Value value() {
+        return (Value) inputs().get(super.inputCount() + INPUT_VALUE);
+    }
+
+    public Value setValue(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_VALUE, n);
+    }
+
+    /**
+     * The opcode for this conversion operation.
+     */
+    public final int opcode;
+
+    /**
+     * Constructs a new Convert instance.
+     * @param opcode the bytecode representing the operation
+     * @param value the instruction producing the input value
+     * @param kind the result type of this instruction
+     * @param graph
+     */
+    public Convert(int opcode, Value value, CiKind kind, Graph graph) {
+        super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.opcode = opcode;
+        setValue(value);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitConvert(this);
+    }
+
+    @Override
+    public int valueNumber() {
+        return Util.hash1(opcode, value());
+    }
+
+    @Override
+    public boolean valueEqual(Node i) {
+        if (i instanceof Convert) {
+            Convert o = (Convert) i;
+            return opcode == o.opcode && value() == o.value();
+        }
+        return false;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(Bytecodes.nameOf(opcode)).print('(').print(value()).print(')');
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        Convert x = new Convert(opcode, null, kind, into);
+        return x;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CreateVectorNode.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,173 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.compiler.ir.Phi.PhiType;
+import com.oracle.max.graal.compiler.phases.LoweringPhase.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class CreateVectorNode extends AbstractVectorNode {
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_LENGTH = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    private boolean reversed;
+
+    public void setLength(Value length) {
+        assert length == null || length.kind == CiKind.Int;
+        inputs().set(super.inputCount() + INPUT_LENGTH, length);
+    }
+
+    public boolean reversed() {
+        return reversed;
+    }
+
+    public void setReversed(boolean r) {
+        reversed = r;
+    }
+
+    public Value length() {
+        return (Value) inputs().get(super.inputCount() + INPUT_LENGTH);
+    }
+
+    public CreateVectorNode(boolean reversed, Value length, Graph graph) {
+        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, null, graph);
+        setLength(length);
+        setReversed(reversed);
+    }
+
+    @Override
+    public Map<Object, Object> getDebugProperties() {
+        Map<Object, Object> debugProperties = super.getDebugProperties();
+        debugProperties.put("reversed", reversed);
+        return debugProperties;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return null;
+        } else if (clazz == LoweringOp.class) {
+            return (T) LOWERING_OP;
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("vector with length ").print(length().toString());
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        CreateVectorNode x = new CreateVectorNode(reversed, null, into);
+        super.copyInto(x);
+        return x;
+    }
+
+    @Override
+    public boolean valueEqual(Node i) {
+        return (i instanceof CreateVectorNode);
+    }
+
+    private LoopBegin createLoop(Map<AbstractVectorNode, Value> map) {
+        EndNode end = new EndNode(graph());
+        LoopBegin loopBegin = new LoopBegin(graph());
+        loopBegin.addEnd(end);
+        Phi loopVariable = new Phi(CiKind.Int, loopBegin, PhiType.Value, graph());
+
+        if (reversed) {
+            IntegerSub add = new IntegerSub(CiKind.Int, loopVariable, Constant.forInt(1, graph()), graph());
+            loopVariable.addInput(new IntegerSub(CiKind.Int, length(), Constant.forInt(1, graph()), graph()));
+            loopVariable.addInput(add);
+        } else {
+            IntegerAdd add = new IntegerAdd(CiKind.Int, loopVariable, Constant.forInt(1, graph()), graph());
+            loopVariable.addInput(Constant.forInt(0, graph()));
+            loopVariable.addInput(add);
+        }
+
+        LoopEnd loopEnd = new LoopEnd(graph());
+        loopEnd.setLoopBegin(loopBegin);
+        loopBegin.setStateAfter(stateAfter());
+        Compare condition;
+        if (reversed) {
+            condition = new Compare(loopVariable, Condition.GE, Constant.forInt(0, graph()), graph());
+        } else {
+            condition = new Compare(loopVariable, Condition.LT, length(), graph());
+        }
+        int expectedLength = 100; // TODO: it may be possible to get a more accurate estimate...?
+        if (length().isConstant()) {
+            expectedLength = length().asConstant().asInt();
+        }
+        If ifNode = new If(condition, 1.0 / expectedLength, graph());
+        loopBegin.setNext(ifNode);
+        ifNode.setTrueSuccessor(loopEnd);
+        this.replaceAtPredecessors(end);
+        ifNode.setFalseSuccessor(this);
+        map.put(this, loopVariable);
+        return loopBegin;
+    }
+
+    private static final LoweringOp LOWERING_OP = new LoweringOp() {
+        @Override
+        public void lower(Node n, CiLoweringTool tool) {
+            CreateVectorNode vectorNode = (CreateVectorNode) n;
+
+            IdentityHashMap<AbstractVectorNode, Value> nodes = new IdentityHashMap<AbstractVectorNode, Value>();
+            LoopBegin begin = vectorNode.createLoop(nodes);
+            for (Node use : vectorNode.usages()) {
+                processUse(begin, use, nodes);
+            }
+        }
+
+        private void processUse(LoopBegin loop, Node use, IdentityHashMap<AbstractVectorNode, Value> nodes) {
+            AbstractVectorNode vectorNode = (AbstractVectorNode) use;
+            if (nodes.containsKey(vectorNode)) {
+                return;
+            }
+            nodes.put(vectorNode, null);
+
+            // Make sure inputs are evaluated.
+            for (Node input : use.inputs()) {
+                if (input instanceof AbstractVectorNode) {
+                    AbstractVectorNode abstractVectorNodeInput = (AbstractVectorNode) input;
+                    processUse(loop, abstractVectorNodeInput, nodes);
+                }
+            }
+
+            vectorNode.addToLoop(loop, nodes);
+
+            // Go on to usages.
+            for (Node usage : use.usages()) {
+                processUse(loop, usage, nodes);
+            }
+        }
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Deoptimize.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+public class Deoptimize extends FixedNode {
+
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    public static enum DeoptAction {
+        None,                           // just interpret, do not invalidate nmethod
+        Recompile,                      // recompile the nmethod; need not invalidate
+        InvalidateReprofile,            // invalidate the nmethod, reset IC, maybe recompile
+        InvalidateRecompile,            // invalidate the nmethod, recompile (probably)
+        InvalidateStopCompiling,        // invalidate the nmethod and do not compile
+    }
+
+    private String message;
+    private final DeoptAction action;
+
+    public Deoptimize(DeoptAction action, Graph graph) {
+        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.action = action;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    public String message() {
+        return message;
+    }
+
+    public DeoptAction action() {
+        return action;
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitDeoptimize(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("deoptimize");
+    }
+
+    @Override
+    public String shortName() {
+        return message == null ? "Deopt " : "Deopt " + message;
+    }
+
+    @Override
+    public Map<Object, Object> getDebugProperties() {
+        Map<Object, Object> properties = super.getDebugProperties();
+        properties.put("message", message);
+        properties.put("action", action);
+        return properties;
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        Deoptimize x = new Deoptimize(action, into);
+        x.setMessage(message);
+        super.copyInto(x);
+        return x;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/EndNode.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,88 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class EndNode extends FixedNode {
+    public static final int SUCCESSOR_COUNT = 0;
+    public static final int INPUT_COUNT = 0;
+
+    public EndNode(Graph graph) {
+        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitEndNode(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("end");
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        EndNode x = new EndNode(into);
+        super.copyInto(x);
+        return x;
+    }
+
+    public Merge merge() {
+        if (usages().size() == 0) {
+            return null;
+        } else {
+            assert usages().size() == 1;
+            return (Merge) usages().get(0);
+        }
+    }
+
+    @Override
+    public boolean verify() {
+        assertTrue(inputs().size() == 0, "inputs empty");
+        assertTrue(successors().size() == 0, "successors empty");
+        assertTrue(usages().size() <= 1, "at most one usage");
+        assertTrue(predecessors().size() <= 1, "at most one predecessor " + predecessors());
+        return true;
+    }
+
+    @Override
+    public Iterable< ? extends Node> dataUsages() {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public Iterable< ? extends Node> cfgSuccessors() {
+        Merge merge = this.merge();
+        if (merge == null) {
+            return Collections.emptyList();
+        }
+        return Arrays.asList(merge);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ExceptionEdgeInstruction.java	Wed Jul 27 17:32:44 2011 -0700
@@ -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.max.graal.compiler.ir;
+
+
+public interface ExceptionEdgeInstruction {
+    FixedNode exceptionEdge();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ExceptionObject.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code ExceptionObject} instruction represents the incoming exception object to an exception handler.
+ */
+public final class ExceptionObject extends StateSplit {
+
+    private static final int INPUT_COUNT = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    /**
+     * Constructs a new ExceptionObject instruction.
+     * @param graph
+     */
+    public ExceptionObject(Graph graph) {
+        super(CiKind.Object, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitExceptionObject(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("incoming exception");
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        ExceptionObject x = new ExceptionObject(into);
+        super.copyInto(x);
+        return x;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FixedGuard.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,107 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.ir.Deoptimize.DeoptAction;
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class FixedGuard extends FixedNodeWithNext {
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    public FixedGuard(BooleanNode node, Graph graph) {
+        this(graph);
+        addNode(node);
+    }
+
+    public FixedGuard(Graph graph) {
+        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitFixedGuard(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("clip node ").print(inputs().toString());
+    }
+
+    public void addNode(BooleanNode node) {
+        variableInputs().add(node);
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        FixedGuard x = new FixedGuard(into);
+        super.copyInto(x);
+        return x;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() {
+        @Override
+        public Node canonical(Node node) {
+            FixedGuard fixedGuard = (FixedGuard) node;
+            Iterator<Node> iter = fixedGuard.variableInputs().iterator();
+            while (iter.hasNext()) {
+                Node n = iter.next();
+                if (n instanceof Constant) {
+                    Constant c = (Constant) n;
+                    if (c.asConstant().asBoolean()) {
+                        if (GraalOptions.TraceCanonicalizer) {
+                            TTY.println("Removing redundant fixed guard " + fixedGuard);
+                        }
+                        iter.remove();
+                    } else {
+                        if (GraalOptions.TraceCanonicalizer) {
+                            TTY.println("Replacing fixed guard " + fixedGuard + " with deoptimization node");
+                        }
+                        return new Deoptimize(DeoptAction.InvalidateRecompile, fixedGuard.graph());
+                    }
+                }
+            }
+
+            if (fixedGuard.variableInputs().size() == 0) {
+                return fixedGuard.next();
+            }
+            return fixedGuard;
+        }
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FixedNode.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,57 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+public abstract class FixedNode extends Value {
+
+    private double probability;
+
+    public FixedNode(CiKind kind, int inputCount, int successorCount, Graph graph) {
+        super(kind, inputCount, successorCount, graph);
+    }
+
+    public double probability() {
+        return probability;
+    }
+
+    public void setProbability(double probability) {
+        this.probability = probability;
+    }
+
+    protected void copyInto(FixedNode newNode) {
+        newNode.setProbability(probability);
+    }
+
+    @Override
+    public Map<Object, Object> getDebugProperties() {
+        Map<Object, Object> properties = super.getDebugProperties();
+        properties.put("probability", String.format(Locale.ENGLISH, "%7.5f", probability));
+        return properties;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FixedNodeWithNext.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+public abstract class FixedNodeWithNext extends FixedNode {
+
+    private static final int INPUT_COUNT = 0;
+
+    private static final int SUCCESSOR_COUNT = 1;
+    public static final int SUCCESSOR_NEXT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * Links to next instruction in a basic block, to {@code null} if this instruction is the end of a basic block or to
+     * itself if not in a block.
+     */
+    public FixedNode next() {
+        return (FixedNode) successors().get(super.successorCount() + SUCCESSOR_NEXT);
+    }
+
+    public Node setNext(FixedNode next) {
+        return successors().set(super.successorCount() + SUCCESSOR_NEXT, next);
+    }
+
+    public static final int SYNCHRONIZATION_ENTRY_BCI = -1;
+
+    /**
+     * Constructs a new instruction with the specified value type.
+     * @param kind the value type for this instruction
+     * @param inputCount
+     * @param successorCount
+     */
+    public FixedNodeWithNext(CiKind kind, int inputCount, int successorCount, Graph graph) {
+        super(kind, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatAdd.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,96 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+
+public final class FloatAdd extends FloatArithmetic {
+    private static final FloatAddCanonicalizerOp CANONICALIZER = new FloatAddCanonicalizerOp();
+
+    public FloatAdd(CiKind kind, Value x, Value y, boolean isStrictFP, Graph graph) {
+        super(kind, kind == CiKind.Double ? Bytecodes.DADD : Bytecodes.FADD, x, y, isStrictFP, graph);
+    }
+
+    @Override
+    public String shortName() {
+        return "+";
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        FloatAdd x = new FloatAdd(kind, null, null, isStrictFP(), into);
+        return x;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static class FloatAddCanonicalizerOp implements CanonicalizerOp {
+        @Override
+        public Node canonical(Node node) {
+            FloatAdd add = (FloatAdd) node;
+            Value x = add.x();
+            Value y = add.y();
+            CiKind kind = add.kind;
+            Graph graph = add.graph();
+            if (x.isConstant() && !y.isConstant()) {
+                add.swapOperands();
+                Value t = y;
+                y = x;
+                x = t;
+            }
+            if (x.isConstant()) {
+                if (kind == CiKind.Float) {
+                    return Constant.forFloat(x.asConstant().asFloat() + y.asConstant().asFloat(), graph);
+                } else {
+                    assert kind == CiKind.Double;
+                    return Constant.forDouble(x.asConstant().asDouble() + y.asConstant().asDouble(), graph);
+                }
+            } else if (y.isConstant()) {
+                if (kind == CiKind.Float) {
+                    float c = y.asConstant().asFloat();
+                    if (c == 0.0f) {
+                        return x;
+                    }
+                } else {
+                    assert kind == CiKind.Double;
+                    double c = y.asConstant().asDouble();
+                    if (c == 0.0) {
+                        return x;
+                    }
+                }
+            }
+            return add;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatArithmetic.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,46 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+/**
+ *
+ */
+public abstract class FloatArithmetic extends Arithmetic {
+
+    /**
+     * @param opcode
+     * @param kind
+     * @param x
+     * @param y
+     * @param isStrictFP
+     * @param graph
+     */
+    public FloatArithmetic(CiKind kind, int opcode, Value x, Value y, boolean isStrictFP, Graph graph) {
+        super(kind, opcode, x, y, isStrictFP, graph);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatDiv.java	Wed Jul 27 17:32:44 2011 -0700
@@ -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.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+public final class FloatDiv extends FloatArithmetic {
+    private static final FloatDivCanonicalizerOp CANONICALIZER = new FloatDivCanonicalizerOp();
+
+    public FloatDiv(CiKind kind, Value x, Value y, boolean isStrictFP, Graph graph) {
+        super(kind, kind == CiKind.Double ? Bytecodes.DDIV : Bytecodes.FDIV, x, y, isStrictFP, graph);
+    }
+
+    @Override
+    public String shortName() {
+        return "/";
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        FloatDiv x = new FloatDiv(kind, null, null, isStrictFP(), into);
+        return x;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static class FloatDivCanonicalizerOp implements CanonicalizerOp {
+        @Override
+        public Node canonical(Node node) {
+            FloatDiv div = (FloatDiv) node;
+            Value x = div.x();
+            Value y = div.y();
+            if (x.isConstant() && y.isConstant()) {
+                CiKind kind = div.kind;
+                Graph graph = div.graph();
+                if (kind == CiKind.Float) {
+                    return Constant.forFloat(x.asConstant().asFloat() / y.asConstant().asFloat(), graph);
+                } else {
+                    assert kind == CiKind.Double;
+                    return Constant.forDouble(x.asConstant().asDouble() / y.asConstant().asDouble(), graph);
+                }
+            }
+            return div;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatMul.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,106 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+
+/**
+ *
+ */
+public final class FloatMul extends FloatArithmetic {
+    private static final FloatMulCanonicalizerOp CANONICALIZER = new FloatMulCanonicalizerOp();
+
+    /**
+     * @param opcode
+     * @param kind
+     * @param x
+     * @param y
+     * @param isStrictFP
+     * @param graph
+     */
+    public FloatMul(CiKind kind, Value x, Value y, boolean isStrictFP, Graph graph) {
+        super(kind, kind == CiKind.Double ? Bytecodes.DMUL : Bytecodes.FMUL, x, y, isStrictFP, graph);
+    }
+
+    @Override
+    public String shortName() {
+        return "*";
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new FloatMul(kind, null, null, isStrictFP(), into);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static class FloatMulCanonicalizerOp implements CanonicalizerOp {
+        @Override
+        public Node canonical(Node node) {
+            FloatMul mul = (FloatMul) node;
+            Value x = mul.x();
+            Value y = mul.y();
+            CiKind kind = mul.kind;
+            Graph graph = mul.graph();
+            if (x.isConstant() && !y.isConstant()) {
+                mul.swapOperands();
+                Value t = y;
+                y = x;
+                x = t;
+            }
+            if (x.isConstant()) {
+                if (kind == CiKind.Float) {
+                    return Constant.forFloat(x.asConstant().asFloat() * y.asConstant().asFloat(), graph);
+                } else {
+                    assert kind == CiKind.Double;
+                    return Constant.forDouble(x.asConstant().asDouble() * y.asConstant().asDouble(), graph);
+                }
+            } else if (y.isConstant()) {
+                if (kind == CiKind.Float) {
+                    float c = y.asConstant().asFloat();
+                    if (c == 0.0f) {
+                        return Constant.forFloat(0.0f, graph);
+                    }
+                } else {
+                    assert kind == CiKind.Double;
+                    double c = y.asConstant().asDouble();
+                    if (c == 0.0) {
+                        return Constant.forDouble(0.0, graph);
+                    }
+                }
+            }
+            return mul;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatRem.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,76 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+
+public final class FloatRem extends FloatArithmetic {
+    private static final FloatRemCanonicalizerOp CANONICALIZER = new FloatRemCanonicalizerOp();
+
+    public FloatRem(CiKind kind, Value x, Value y, boolean isStrictFP, Graph graph) {
+        super(kind, kind == CiKind.Double ? Bytecodes.DREM : Bytecodes.FREM, x, y, isStrictFP, graph);
+    }
+
+    @Override
+    public String shortName() {
+        return "%";
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new FloatRem(kind, null, null, isStrictFP(), into);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static class FloatRemCanonicalizerOp implements CanonicalizerOp {
+        @Override
+        public Node canonical(Node node) {
+            FloatRem rem = (FloatRem) node;
+            Value x = rem.x();
+            Value y = rem.y();
+            if (x.isConstant() && y.isConstant()) {
+                CiKind kind = rem.kind;
+                Graph graph = rem.graph();
+                if (kind == CiKind.Float) {
+                    return Constant.forFloat(x.asConstant().asFloat() % y.asConstant().asFloat(), graph);
+                } else {
+                    assert kind == CiKind.Double;
+                    return Constant.forDouble(x.asConstant().asDouble() % y.asConstant().asDouble(), graph);
+                }
+            }
+            return rem;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatSub.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,99 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+
+public final class FloatSub extends FloatArithmetic {
+    private static final FloatSubCanonicalizerOp CANONICALIZER = new FloatSubCanonicalizerOp();
+
+    public FloatSub(CiKind kind, Value x, Value y, boolean isStrictFP, Graph graph) {
+        super(kind, kind == CiKind.Double ? Bytecodes.DSUB : Bytecodes.FSUB, x, y, isStrictFP, graph);
+    }
+
+    @Override
+    public String shortName() {
+        return "-";
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new FloatSub(kind, null, null, isStrictFP(), into);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static class FloatSubCanonicalizerOp implements CanonicalizerOp {
+        @Override
+        public Node canonical(Node node) {
+            FloatSub sub = (FloatSub) node;
+            Value x = sub.x();
+            Value y = sub.y();
+            CiKind kind = sub.kind;
+            Graph graph = sub.graph();
+            if (x == y) {
+                if (kind == CiKind.Float) {
+                    return Constant.forFloat(0.0f, graph);
+                } else {
+                    assert kind == CiKind.Double;
+                    return Constant.forDouble(0.0, graph);
+                }
+            }
+            if (x.isConstant() && y.isConstant()) {
+                if (kind == CiKind.Float) {
+                    return Constant.forFloat(x.asConstant().asFloat() - y.asConstant().asFloat(), graph);
+                } else {
+                    assert kind == CiKind.Double;
+                    return Constant.forDouble(x.asConstant().asDouble() - y.asConstant().asDouble(), graph);
+                }
+            } else if (y.isConstant()) {
+                if (kind == CiKind.Float) {
+                    float c = y.asConstant().asFloat();
+                    if (c == 0.0f) {
+                        return x;
+                    }
+                    return new FloatAdd(kind, x, Constant.forFloat(-c, graph), sub.isStrictFP(), graph);
+                } else {
+                    assert kind == CiKind.Double;
+                    double c = y.asConstant().asDouble();
+                    if (c == 0.0) {
+                        return x;
+                    }
+                    return new FloatAdd(kind, x, Constant.forDouble(-c, graph), sub.isStrictFP(), graph);
+                }
+            }
+            return sub;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatingNode.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,41 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public abstract class FloatingNode extends Value {
+
+    /**
+     * @param kind
+     * @param inputCount
+     * @param successorCount
+     * @param graph
+     */
+    public FloatingNode(CiKind kind, int inputCount, int successorCount, Graph graph) {
+        super(kind, inputCount, successorCount, graph);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/GuardNode.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,108 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class GuardNode extends FloatingNode {
+    private static final int INPUT_COUNT = 2;
+    private static final int INPUT_ANCHOR = 0;
+    private static final int INPUT_NODE = 1;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    public FixedNode anchor() {
+        return (FixedNode) inputs().get(super.inputCount() + INPUT_ANCHOR);
+    }
+
+    public void setAnchor(FixedNode anchor) {
+        inputs().set(super.inputCount() + INPUT_ANCHOR, anchor);
+    }
+
+    /**
+     * The instruction that produces the object tested against null.
+     */
+    public BooleanNode node() {
+        return (BooleanNode) inputs().get(super.inputCount() + INPUT_NODE);
+    }
+
+    public void setNode(BooleanNode n) {
+        inputs().set(super.inputCount() + INPUT_NODE, n);
+    }
+
+    public GuardNode(BooleanNode node, Graph graph) {
+        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        setNode(node);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitGuardNode(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("guard node ").print(node());
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new GuardNode(null, into);
+    }
+
+    @Override
+    public boolean valueEqual(Node i) {
+        return i instanceof GuardNode;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() {
+        @Override
+        public Node canonical(Node node) {
+            GuardNode guard = (GuardNode) node;
+            if (guard.node() instanceof Constant) {
+                Constant c = (Constant) guard.node();
+                if (c.asConstant().asBoolean()) {
+                    if (GraalOptions.TraceCanonicalizer) {
+                        TTY.println("Removing redundant floating guard " + guard);
+                    }
+                    return Node.Null;
+                }
+            }
+            return guard;
+        }
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/If.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code If} instruction represents a branch that can go one of two directions
+ * depending on the outcome of a comparison.
+ */
+public final class If extends ControlSplit {
+
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_COMPARE = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The instruction that produces the first input to this comparison.
+     */
+     public BooleanNode compare() {
+        return (BooleanNode) inputs().get(super.inputCount() + INPUT_COMPARE);
+    }
+
+    public void setCompare(BooleanNode n) {
+        inputs().set(super.inputCount() + INPUT_COMPARE, n);
+    }
+
+    public If(BooleanNode condition, double probability, Graph graph) {
+        super(CiKind.Illegal, 2, new double[] {probability, 1 - probability}, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        setCompare(condition);
+    }
+
+    /**
+     * Gets the block corresponding to the true successor.
+     * @return the true successor
+     */
+    public FixedNode trueSuccessor() {
+        return blockSuccessor(0);
+    }
+
+    /**
+     * Gets the block corresponding to the false successor.
+     * @return the false successor
+     */
+    public FixedNode falseSuccessor() {
+        return blockSuccessor(1);
+    }
+
+
+    public void setTrueSuccessor(FixedNode node) {
+        setBlockSuccessor(0, node);
+    }
+
+
+    public void setFalseSuccessor(FixedNode node) {
+        setBlockSuccessor(1, node);
+    }
+
+    /**
+     * Gets the block corresponding to the specified outcome of the branch.
+     * @param istrue {@code true} if the true successor is requested, {@code false} otherwise
+     * @return the corresponding successor
+     */
+    public FixedNode successor(boolean istrue) {
+        return blockSuccessor(istrue ? 0 : 1);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitIf(this);
+    }
+
+    @Override
+    public boolean verify() {
+        assertTrue(compare() != null);
+        assertTrue(trueSuccessor() != null);
+        assertTrue(falseSuccessor() != null);
+        return true;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("if ").
+        print(compare()).
+        print(" then ").
+        print(trueSuccessor()).
+        print(" else ").
+        print(falseSuccessor());
+    }
+
+    @Override
+    public String shortName() {
+        return "If";
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        If x = new If(null, probability(0), into);
+        super.copyInto(x);
+        return x;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() {
+        @Override
+        public Node canonical(Node node) {
+            If ifNode = (If) node;
+            if (ifNode.compare() instanceof Constant) {
+                Constant c = (Constant) ifNode.compare();
+                if (c.asConstant().asBoolean()) {
+                    if (GraalOptions.TraceCanonicalizer) {
+                        TTY.println("Replacing if " + ifNode + " with true branch");
+                    }
+                    return ifNode.trueSuccessor();
+                } else {
+                    if (GraalOptions.TraceCanonicalizer) {
+                        TTY.println("Replacing if " + ifNode + " with false branch");
+                    }
+                    return ifNode.falseSuccessor();
+                }
+            }
+            return ifNode;
+        }
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/InstanceOf.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp;
+import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code InstanceOf} instruction represents an instanceof test.
+ */
+public final class InstanceOf extends TypeCheck {
+
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    private boolean nullIsTrue;
+
+    /**
+     * Constructs a new InstanceOf instruction.
+     * @param targetClass the target class of the instanceof check
+     * @param object the instruction producing the object input to this instruction
+     * @param graph
+     */
+    public InstanceOf(Constant targetClassInstruction, Value object, boolean nullIsTrue, Graph graph) {
+        super(targetClassInstruction, object, CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+    }
+
+    @Override
+    public int valueNumber() {
+        return Util.hash1(Bytecodes.INSTANCEOF, object());
+    }
+
+    @Override
+    public boolean valueEqual(Node i) {
+        return i instanceof InstanceOf;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("instanceof(").print(object()).print(") ").print(CiUtil.toJavaName(targetClass()));
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new InstanceOf(null, null, nullIsTrue, into);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() {
+        @Override
+        public Node canonical(Node node) {
+            InstanceOf isInstance = (InstanceOf) node;
+            Value object = isInstance.object();
+            RiType exactType = object.exactType();
+            if (exactType != null) {
+                return Constant.forBoolean(exactType.isSubtypeOf(isInstance.targetClass()), node.graph());
+            }
+            CiConstant constant = object.asConstant();
+            if (constant != null) {
+                assert constant.kind == CiKind.Object;
+                if (constant.isNull()) {
+                    return Constant.forBoolean(false, node.graph());
+                } else {
+                    // this should never happen - non-null constants are always expected to provide an exactType
+                    assert false;
+                }
+            }
+            return isInstance;
+        }
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerAdd.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+
+public final class IntegerAdd extends IntegerArithmeticNode {
+    private static final IntegerAddCanonicalizerOp CANONICALIZER = new IntegerAddCanonicalizerOp();
+
+    public IntegerAdd(CiKind kind, Value x, Value y, Graph graph) {
+        super(kind, kind == CiKind.Int ? Bytecodes.IADD : Bytecodes.LADD, x, y, graph);
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new IntegerAdd(kind, null, null, into);
+    }
+
+    @Override
+    public String shortName() {
+        return "+";
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static class IntegerAddCanonicalizerOp implements CanonicalizerOp {
+        @Override
+        public Node canonical(Node node) {
+            IntegerAdd add = (IntegerAdd) node;
+            Value x = add.x();
+            Value y = add.y();
+            CiKind kind = add.kind;
+            Graph graph = add.graph();
+            if (x.isConstant() && !y.isConstant()) {
+                add.swapOperands();
+                Value t = y;
+                y = x;
+                x = t;
+            }
+            if (x.isConstant()) {
+                if (kind == CiKind.Int) {
+                    return Constant.forInt(x.asConstant().asInt() + y.asConstant().asInt(), graph);
+                } else {
+                    assert kind == CiKind.Long;
+                    return Constant.forLong(x.asConstant().asLong() + y.asConstant().asLong(), graph);
+                }
+            } else if (y.isConstant()) {
+                if (kind == CiKind.Int) {
+                    int c = y.asConstant().asInt();
+                    if (c == 0) {
+                        return x;
+                    }
+                } else {
+                    assert kind == CiKind.Long;
+                    long c = y.asConstant().asLong();
+                    if (c == 0) {
+                        return x;
+                    }
+                }
+            }
+            return add;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerAddVectorNode.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class IntegerAddVectorNode extends AbstractVectorNode {
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_VALUE = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    public Value value() {
+        return (Value) inputs().get(super.inputCount() + INPUT_VALUE);
+    }
+
+    public void setValue(Value v) {
+        inputs().set(super.inputCount() + INPUT_VALUE, v);
+    }
+
+    public IntegerAddVectorNode(AbstractVectorNode vector, Value value, Graph graph) {
+        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, vector, graph);
+        setValue(value);
+    }
+
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return null;
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        IntegerAddVectorNode x = new IntegerAddVectorNode(null, null, into);
+        super.copyInto(x);
+        return x;
+    }
+
+    @Override
+    public void addToLoop(LoopBegin loop, IdentityHashMap<AbstractVectorNode, Value> nodes) {
+        nodes.put(this, new IntegerAdd(CiKind.Int, nodes.get(vector()), value(), graph()));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerArithmeticNode.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public abstract class IntegerArithmeticNode extends Arithmetic {
+
+    public IntegerArithmeticNode(CiKind kind, int opcode, Value x, Value y, Graph graph) {
+        super(kind, opcode, x, y, false, graph);
+        assert kind == CiKind.Int || kind == CiKind.Long;
+    }
+
+    public static IntegerArithmeticNode add(Value v1, Value v2) {
+        assert v1.kind == v2.kind && v1.graph() == v2.graph();
+        Graph graph = v1.graph();
+        //TODO (gd) handle conversions here instead of strong assert ?
+        switch(v1.kind) {
+            case Int:
+                return new IntegerAdd(CiKind.Int, v1, v2, graph);
+            case Long:
+                return new IntegerAdd(CiKind.Long, v1, v2, graph);
+            default:
+                throw Util.shouldNotReachHere();
+        }
+    }
+
+    public static IntegerArithmeticNode mul(Value v1, Value v2) {
+        assert v1.kind == v2.kind && v1.graph() == v2.graph();
+        Graph graph = v1.graph();
+        //TODO (gd) handle conversions here instead of strong assert ?
+        switch(v1.kind) {
+            case Int:
+                return new IntegerMul(CiKind.Int, v1, v2, graph);
+            case Long:
+                return new IntegerMul(CiKind.Long, v1, v2, graph);
+            default:
+                throw Util.shouldNotReachHere();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerDiv.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,85 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+
+public final class IntegerDiv extends IntegerArithmeticNode {
+    private static final IntegerDivCanonicalizerOp CANONICALIZER = new IntegerDivCanonicalizerOp();
+
+    public IntegerDiv(CiKind kind, Value x, Value y, Graph graph) {
+        super(kind, kind == CiKind.Int ? Bytecodes.IDIV : Bytecodes.LDIV, x, y, graph);
+    }
+
+    @Override
+    public String shortName() {
+        return "/";
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new IntegerDiv(kind, null, null, into);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static class IntegerDivCanonicalizerOp implements CanonicalizerOp {
+        @Override
+        public Node canonical(Node node) {
+            IntegerDiv div = (IntegerDiv) node;
+            Value x = div.x();
+            Value y = div.y();
+            CiKind kind = div.kind;
+            Graph graph = div.graph();
+            if (x.isConstant() && y.isConstant()) {
+                long yConst = y.asConstant().asLong();
+                if (yConst == 0) {
+                    return div; // this will trap, can not canonicalize
+                }
+                if (kind == CiKind.Int) {
+                    return Constant.forInt(x.asConstant().asInt() / (int) yConst, graph);
+                } else {
+                    assert kind == CiKind.Long;
+                    return Constant.forLong(x.asConstant().asLong() / yConst, graph);
+                }
+            } else if (y.isConstant()) {
+                long c = y.asConstant().asLong();
+                if (c == 1) {
+                    return x;
+                }
+            }
+            return div;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerMul.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,93 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+
+public final class IntegerMul extends IntegerArithmeticNode {
+    private static final IntegerMulCanonicalizerOp CANONICALIZER = new IntegerMulCanonicalizerOp();
+
+    public IntegerMul(CiKind kind, Value x, Value y, Graph graph) {
+        super(kind, kind == CiKind.Int ? Bytecodes.IMUL : Bytecodes.LMUL, x, y, graph);
+    }
+
+    @Override
+    public String shortName() {
+        return "*";
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new IntegerMul(kind, null, null, into);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static class IntegerMulCanonicalizerOp implements CanonicalizerOp {
+        @Override
+        public Node canonical(Node node) {
+            IntegerMul mul = (IntegerMul) node;
+            Value x = mul.x();
+            Value y = mul.y();
+            CiKind kind = mul.kind;
+            Graph graph = mul.graph();
+            if (x.isConstant() && !y.isConstant()) {
+                mul.swapOperands();
+                Value t = y;
+                y = x;
+                x = t;
+            }
+            if (x.isConstant()) {
+                if (kind == CiKind.Int) {
+                    return Constant.forInt(x.asConstant().asInt() * y.asConstant().asInt(), graph);
+                } else {
+                    assert kind == CiKind.Long;
+                    return Constant.forLong(x.asConstant().asLong() * y.asConstant().asLong(), graph);
+                }
+            } else if (y.isConstant()) {
+                long c = y.asConstant().asLong();
+                if (c == 1) {
+                    return x;
+                }
+                if (c == 0) {
+                    return Constant.forInt(0, graph);
+                }
+                if (c > 0 && CiUtil.isPowerOf2(c)) {
+                    return new LeftShift(kind, x, Constant.forInt(CiUtil.log2(c), graph), graph);
+                }
+            }
+            return mul;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerRem.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,85 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+
+public final class IntegerRem extends IntegerArithmeticNode {
+    private static final IntegerRemCanonicalizerOp CANONICALIZER = new IntegerRemCanonicalizerOp();
+
+    public IntegerRem(CiKind kind, Value x, Value y, Graph graph) {
+        super(kind, kind == CiKind.Int ? Bytecodes.IREM : Bytecodes.LREM, x, y, graph);
+    }
+
+    @Override
+    public String shortName() {
+        return "%";
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new IntegerRem(kind, null, null, into);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static class IntegerRemCanonicalizerOp implements CanonicalizerOp {
+        @Override
+        public Node canonical(Node node) {
+            IntegerRem rem = (IntegerRem) node;
+            Value x = rem.x();
+            Value y = rem.y();
+            CiKind kind = rem.kind;
+            Graph graph = rem.graph();
+            if (x.isConstant() && y.isConstant()) {
+                long yConst = y.asConstant().asLong();
+                if (yConst == 0) {
+                    return rem; // this will trap, can not canonicalize
+                }
+                if (kind == CiKind.Int) {
+                    return Constant.forInt(x.asConstant().asInt() % (int) yConst, graph);
+                } else {
+                    assert kind == CiKind.Long;
+                    return Constant.forLong(x.asConstant().asLong() % yConst, graph);
+                }
+            } else if (y.isConstant()) {
+                long c = y.asConstant().asLong();
+                if (c == 1) {
+                    return x;
+                }
+            }
+            return rem;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerSub.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+
+public final class IntegerSub extends IntegerArithmeticNode {
+    private static final IntegerSubCanonicalizerOp CANONICALIZER = new IntegerSubCanonicalizerOp();
+
+    public IntegerSub(CiKind kind, Value x, Value y, Graph graph) {
+        super(kind, kind == CiKind.Int ? Bytecodes.ISUB : Bytecodes.LSUB, x, y, graph);
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new IntegerSub(kind, null, null, into);
+    }
+
+    @Override
+    public String shortName() {
+        return "-";
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static class IntegerSubCanonicalizerOp implements CanonicalizerOp {
+        @Override
+        public Node canonical(Node node) {
+            IntegerSub sub = (IntegerSub) node;
+            Value x = sub.x();
+            Value y = sub.y();
+            CiKind kind = sub.kind;
+            Graph graph = sub.graph();
+            if (x == y) {
+                if (kind == CiKind.Int) {
+                    return Constant.forInt(0, graph);
+                } else {
+                    assert kind == CiKind.Long;
+                    return Constant.forLong(0, graph);
+                }
+            }
+            if (x.isConstant() && y.isConstant()) {
+                if (kind == CiKind.Int) {
+                    return Constant.forInt(x.asConstant().asInt() - y.asConstant().asInt(), graph);
+                } else {
+                    assert kind == CiKind.Long;
+                    return Constant.forLong(x.asConstant().asLong() - y.asConstant().asLong(), graph);
+                }
+            } else if (y.isConstant()) {
+                long c = y.asConstant().asLong();
+                if (c == 0) {
+                    return x;
+                }
+                if (kind == CiKind.Int) {
+                    return new IntegerAdd(kind, x, Constant.forInt((int) -c, graph), graph);
+                } else {
+                    assert kind ==  CiKind.Long;
+                    return new IntegerAdd(kind, x, Constant.forLong(-c, graph), graph);
+                }
+            } else if (x.isConstant()) {
+                long c = x.asConstant().asLong();
+                if (c == 0) {
+                    return new Negate(y, graph);
+                }
+            }
+            return sub;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Invoke.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code Invoke} instruction represents all kinds of method calls.
+ */
+public final class Invoke extends AbstractMemoryCheckpointNode implements ExceptionEdgeInstruction {
+
+    private final int argumentCount;
+
+    private static final int SUCCESSOR_COUNT = 1;
+    private static final int SUCCESSOR_EXCEPTION_EDGE = 0;
+
+    private boolean canInline = true;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + argumentCount;
+    }
+
+    public boolean canInline() {
+        return canInline;
+    }
+
+    public void setCanInline(boolean b) {
+        canInline = b;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    public List<Value> arguments() {
+        return new AbstractList<Value>() {
+            @Override
+            public int size() {
+                return argumentCount;
+            }
+
+            @Override
+            public Value get(int index) {
+                return (Value) inputs().get(Invoke.super.inputCount() + index);
+            }
+
+            @Override
+            public Value set(int index, Value node) {
+                return (Value) inputs().set(Invoke.super.inputCount() + index, node);
+            }
+        };
+
+    }
+
+    /**
+     * The entry to the exception dispatch chain for this invoke.
+     */
+    @Override
+    public FixedNode exceptionEdge() {
+        return (FixedNode) successors().get(super.successorCount() + SUCCESSOR_EXCEPTION_EDGE);
+    }
+
+    public FixedNode setExceptionEdge(FixedNode n) {
+        return (FixedNode) successors().set(super.successorCount() + SUCCESSOR_EXCEPTION_EDGE, n);
+    }
+
+    public final int opcode;
+    public final RiMethod target;
+    public final RiType returnType;
+    public final int bci; // XXX needed because we can not compute the bci from the sateBefore bci of this Invoke was optimized from INVOKEINTERFACE to INVOKESPECIAL
+
+    /**
+     * Constructs a new Invoke instruction.
+     *
+     * @param opcode the opcode of the invoke
+     * @param result the result type
+     * @param args the list of instructions producing arguments to the invocation, including the receiver object
+     * @param isStatic {@code true} if this call is static (no receiver object)
+     * @param target the target method being called
+     */
+    public Invoke(int bci, int opcode, CiKind result, Value[] args, RiMethod target, RiType returnType, Graph graph) {
+        super(result, args.length, SUCCESSOR_COUNT, graph);
+        this.opcode = opcode;
+        this.target = target;
+        this.returnType = returnType;
+        this.bci = bci;
+
+        this.argumentCount = args.length;
+        for (int i = 0; i < args.length; i++) {
+            arguments().set(i, args[i]);
+        }
+    }
+
+    /**
+     * Gets the opcode of this invoke instruction.
+     * @return the opcode
+     */
+    public int opcode() {
+        return opcode;
+    }
+
+    /**
+     * Checks whether this is an invocation of a static method.
+     * @return {@code true} if the invocation is a static invocation
+     */
+    public boolean isStatic() {
+        return opcode == Bytecodes.INVOKESTATIC;
+    }
+
+    @Override
+    public RiType declaredType() {
+        return returnType;
+    }
+
+    /**
+     * 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
+     */
+    public Value receiver() {
+        assert !isStatic();
+        return arguments().get(0);
+    }
+
+    /**
+     * Gets the target method for this invocation instruction.
+     * @return the target method
+     */
+    public RiMethod target() {
+        return target;
+    }
+
+    /**
+     * Checks whether this invocation has a receiver object.
+     * @return {@code true} if this invocation has a receiver object; {@code false} otherwise, if this is a
+     *         static call
+     */
+    public boolean hasReceiver() {
+        return !isStatic();
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitInvoke(this);
+    }
+
+    public CiKind[] signature() {
+        CiKind receiver = isStatic() ? null : target.holder().kind();
+        return Util.signatureToKinds(target.signature(), receiver);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        int argStart = 0;
+        if (hasReceiver()) {
+            out.print(receiver()).print('.');
+            argStart = 1;
+        }
+
+        RiMethod target = target();
+        out.print(target.name()).print('(');
+        for (int i = argStart; i < argumentCount; i++) {
+            if (i > argStart) {
+                out.print(", ");
+            }
+            out.print(arguments().get(i));
+        }
+        out.print(CiUtil.format(") [method: %H.%n(%p):%r]", target, false));
+    }
+
+    @Override
+    public String toString() {
+        return super.toString() + target;
+    }
+
+    @Override
+    public Map<Object, Object> getDebugProperties() {
+        Map<Object, Object> properties = super.getDebugProperties();
+        properties.put("opcode", Bytecodes.nameOf(opcode));
+        properties.put("target", CiUtil.format("%H.%n(%p):%r", target, false));
+        properties.put("bci", bci);
+        return properties;
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        Invoke x = new Invoke(bci, opcode, kind, new Value[argumentCount], target, returnType, into);
+        x.setCanInline(canInline);
+        super.copyInto(x);
+        return x;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IsNonNull.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp;
+import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code NullCheck} class represents an explicit null check instruction.
+ */
+public final class IsNonNull extends BooleanNode {
+
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_OBJECT = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The instruction that produces the object tested against null.
+     */
+     public Value object() {
+        return (Value) inputs().get(super.inputCount() + INPUT_OBJECT);
+    }
+
+    public Value setObject(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_OBJECT, n);
+    }
+
+    /**
+     * Constructs a new NullCheck instruction.
+     * @param object the instruction producing the object to check against null
+     * @param graph
+     */
+    public IsNonNull(Value object, Graph graph) {
+        super(CiKind.Object, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        assert object == null || object.kind == CiKind.Object : object;
+        setObject(object);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        // Nothing to do.
+    }
+
+    @Override
+    public int valueNumber() {
+        return Util.hash1(Bytecodes.IFNONNULL, object());
+    }
+
+    @Override
+    public boolean valueEqual(Node i) {
+        return i instanceof IsNonNull;
+    }
+
+    @Override
+    public RiType declaredType() {
+        // null check does not alter the type of the object
+        return object().declaredType();
+    }
+
+    @Override
+    public RiType exactType() {
+        // null check does not alter the type of the object
+        return object().exactType();
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("null_check(").print(object()).print(')');
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new IsNonNull(null, into);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() {
+        @Override
+        public Node canonical(Node node) {
+            IsNonNull isNonNull = (IsNonNull) node;
+            Value object = isNonNull.object();
+            if (object instanceof NewInstance || object instanceof NewArray) {
+                return Constant.forBoolean(true, node.graph());
+            }
+            CiConstant constant = object.asConstant();
+            if (constant != null) {
+                assert constant.kind == CiKind.Object;
+                return Constant.forBoolean(constant.isNonNull(), node.graph());
+            }
+            return isNonNull;
+        }
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IsType.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp;
+import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code TypeCheck} class represents an explicit type check instruction.
+ */
+public final class IsType extends BooleanNode {
+
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_OBJECT = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The instruction that produces the object tested against null.
+     */
+     public Value object() {
+        return (Value) inputs().get(super.inputCount() + INPUT_OBJECT);
+    }
+
+    public Value setObject(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_OBJECT, n);
+    }
+
+    private final RiType type;
+
+    /**
+     * Constructs a new IsType instruction.
+     * @param object the instruction producing the object to check against the given type
+     * @param graph
+     */
+    public IsType(Value object, RiType type, Graph graph) {
+        super(CiKind.Object, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        assert type.isResolved();
+        assert object == null || object.kind == CiKind.Object;
+        this.type = type;
+        setObject(object);
+    }
+
+    public RiType type() {
+        return type;
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        // Nothing to do.
+    }
+
+    @Override
+    public int valueNumber() {
+        return Util.hash1(Bytecodes.CHECKCAST, object());
+    }
+
+    @Override
+    public boolean valueEqual(Node i) {
+        if (i instanceof IsType) {
+            IsType o = (IsType) i;
+            return type == o.type();
+        }
+        return false;
+    }
+
+    @Override
+    public RiType declaredType() {
+        // type check does not alter the type of the object
+        return object().declaredType();
+    }
+
+    @Override
+    public RiType exactType() {
+        return type;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("null_check(").print(object()).print(')');
+    }
+
+    @Override
+    public Map<Object, Object> getDebugProperties() {
+        Map<Object, Object> properties = super.getDebugProperties();
+        properties.put("type", type);
+        return properties;
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new IsType(null, type, into);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() {
+        @Override
+        public Node canonical(Node node) {
+            IsType isType = (IsType) node;
+            Value object = isType.object();
+            RiType exactType = object.exactType();
+            if (exactType != null) {
+                return Constant.forBoolean(exactType == isType.type, node.graph());
+            }
+            // constants return the correct exactType, so they are handled by the code above
+            return isType;
+        }
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LeftShift.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,115 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+
+public final class LeftShift extends Shift {
+    private static final LeftShiftCanonicalizerOp CANONICALIZER = new LeftShiftCanonicalizerOp();
+
+    public LeftShift(CiKind kind, Value x, Value y, Graph graph) {
+        super(kind, kind == CiKind.Int ? Bytecodes.ISHL : Bytecodes.LSHL, x, y, graph);
+    }
+
+    @Override
+    public String shortName() {
+        return "<<";
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        LeftShift ls = new LeftShift(kind, null, null, into);
+        return ls;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static class LeftShiftCanonicalizerOp implements CanonicalizerOp {
+        @Override
+        public Node canonical(Node node) {
+            LeftShift leftShift = (LeftShift) node;
+            CiKind kind = leftShift.kind;
+            Graph graph = leftShift.graph();
+            Value value = leftShift.x();
+            Value y = leftShift.y();
+            if (y.isConstant()) {
+                int amount = y.asConstant().asInt();
+                int originalAmout = amount;
+                int mask;
+                if (kind == CiKind.Int) {
+                    mask = 0x1f;
+                } else {
+                    assert kind == CiKind.Long;
+                    mask = 0x3f;
+                }
+                amount &= mask;
+                if (value.isConstant()) {
+                    if (kind == CiKind.Int) {
+                        return Constant.forInt(value.asConstant().asInt() << amount, graph);
+                    } else {
+                        assert kind == CiKind.Long;
+                        return Constant.forLong(value.asConstant().asLong() << amount, graph);
+                    }
+                }
+                if (amount == 0) {
+                    return value;
+                }
+                if (value instanceof Shift) {
+                    Shift other = (Shift) value;
+                    if (other.y().isConstant()) {
+                        int otherAmount = other.y().asConstant().asInt() & mask;
+                        if (other instanceof LeftShift) {
+                            int total = amount + otherAmount;
+                            if (total != (total & mask)) {
+                                return Constant.forInt(0, graph);
+                            }
+                            return new LeftShift(kind, other.x(), Constant.forInt(total, graph), graph);
+                        } else if ((other instanceof RightShift || other instanceof UnsignedRightShift) && otherAmount == amount) {
+                            if (kind == CiKind.Long) {
+                                return new And(kind, other.x(), Constant.forLong(-1L << amount, graph), graph);
+                            } else {
+                                assert kind == CiKind.Int;
+                                return new And(kind, other.x(), Constant.forInt(-1 << amount, graph), graph);
+                            }
+                        }
+                    }
+                }
+                if (originalAmout != amount) {
+                    return new LeftShift(kind, value, Constant.forInt(amount, graph), graph);
+                }
+            }
+            return leftShift;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoadField.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp;
+import com.oracle.max.graal.compiler.phases.*;
+import com.oracle.max.graal.compiler.phases.LoweringPhase.LoweringOp;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code LoadField} instruction represents a read of a static or instance field.
+ */
+public final class LoadField extends AccessField {
+    private static final LoadFieldCanonicalizerOp CANONICALIZER = new LoadFieldCanonicalizerOp();
+
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    /**
+     * Creates a new LoadField instance.
+     * @param object the receiver object
+     * @param field the compiler interface field
+     * @param isStatic indicates if the field is static
+     * @param stateAfter the state after the field access
+     * @param graph
+     * @param isLoaded indicates if the class is loaded
+     */
+    public LoadField(Value object, RiField field, Graph graph) {
+        super(field.kind().stackKind(), object, field, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+    }
+
+    /**
+     * Gets the declared type of the field being accessed.
+     * @return the declared type of the field being accessed.
+     */
+    @Override
+    public RiType declaredType() {
+        return field().type();
+    }
+
+    /**
+     * Gets the exact type of the field being accessed. If the field type is
+     * a primitive array or an instance class and the class is loaded and final,
+     * then the exact type is the same as the declared type. Otherwise it is {@code null}
+     * @return the exact type of the field if known; {@code null} otherwise
+     */
+    @Override
+    public RiType exactType() {
+        RiType declared = declaredType();
+        return declared != null && declared.isResolved() ? declared.exactType() : null;
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitLoadField(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(object()).
+        print(".").
+        print(field.name()).
+        print(" [field: ").
+        print(CiUtil.format("%h.%n:%t", field, false)).
+        print("]");
+    }
+
+    @Override
+    public boolean needsStateAfter() {
+        return false;
+    }
+
+    /**
+     * Gets a constant value to which this load can be reduced.
+     *
+     * @return {@code null} if this load cannot be reduced to a constant
+     */
+    private CiConstant constantValue() {
+        if (isStatic()) {
+            return field.constantValue(null);
+        } else if (object().isConstant()) {
+            return field.constantValue(object().asConstant());
+        }
+        return null;
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        LoadField x = new LoadField(null, field, into);
+        super.copyInto(x);
+        return x;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        } else if (clazz == LoweringOp.class) {
+            return (T) LoweringPhase.DELEGATE_TO_RUNTIME;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static class LoadFieldCanonicalizerOp implements CanonicalizerOp {
+        @Override
+        public Node canonical(Node node) {
+            LoadField loadField = (LoadField) node;
+            Graph graph = node.graph();
+            CiConstant constant = null;
+            if (loadField.isStatic()) {
+                    constant = loadField.field().constantValue(null);
+            } else {
+                Value object = loadField.object();
+                if (object.isConstant()) {
+                    constant = loadField.field().constantValue(object.asConstant());
+                }
+            }
+            if (constant != null) {
+                return new Constant(constant, graph);
+            }
+            return loadField;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoadIndexed.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.phases.*;
+import com.oracle.max.graal.compiler.phases.LoweringPhase.LoweringOp;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code LoadIndexed} instruction represents a read from an element of an array.
+ */
+public final class LoadIndexed extends AccessIndexed {
+
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    /**
+     * Creates a new LoadIndexed instruction.
+     * @param array the instruction producing the array
+     * @param index the instruction producing the index
+     * @param length the instruction producing the length
+     * @param elementKind the element type
+     * @param graph
+     */
+    public LoadIndexed(Value array, Value index, Value length, CiKind elementKind, Graph graph) {
+        super(elementKind.stackKind(), array, index, length, elementKind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+    }
+
+    /**
+     * Gets the declared type of this instruction's result.
+     * @return the declared type
+     */
+    @Override
+    public RiType declaredType() {
+        RiType arrayType = array().declaredType();
+        if (arrayType == null) {
+            return null;
+        }
+        return arrayType.componentType();
+    }
+
+    /**
+     * Gets the exact type of this instruction's result.
+     * @return the exact type
+     */
+    @Override
+    public RiType exactType() {
+        RiType declared = declaredType();
+        return declared != null && declared.isResolved() ? declared.exactType() : null;
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitLoadIndexed(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(array()).print('[').print(index()).print("] (").print(kind.typeChar).print(')');
+    }
+
+    @Override
+    public boolean needsStateAfter() {
+        return false;
+    }
+
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LoweringOp.class) {
+            return (T) LoweringPhase.DELEGATE_TO_RUNTIME;
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        LoadIndexed x = new LoadIndexed(null, null, null, elementKind(), into);
+        super.copyInto(x);
+        return x;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Local.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code Local} instruction is a placeholder for an incoming argument
+ * to a function call.
+ */
+public final class Local extends FloatingNode {
+
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_START = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The start node of the graph that this local belongs to. This is used for correctly scheduling the locals.
+     */
+     private StartNode start() {
+        return (StartNode) inputs().get(super.inputCount() + INPUT_START);
+    }
+
+     private void setStart(StartNode n) {
+         inputs().set(super.inputCount() + INPUT_START, n);
+     }
+
+    private final int index;
+    private RiType declaredType;
+
+    public Local(CiKind kind, int javaIndex, Graph graph) {
+        super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.index = javaIndex;
+        setStart(graph.start());
+    }
+
+    /**
+     * Gets the index of this local.
+     * @return the index
+     */
+    public int index() {
+        return index;
+    }
+
+    /**
+     * Sets the declared type of this local, e.g. derived from the signature of the method.
+     * @param declaredType the declared type of the local variable
+     */
+    public void setDeclaredType(RiType declaredType) {
+        this.declaredType = declaredType;
+    }
+
+    /**
+     * Computes the declared type of the result of this instruction, if possible.
+     * @return the declared type of the result of this instruction, if it is known; {@code null} otherwise
+     */
+    @Override
+    public RiType declaredType() {
+        return declaredType;
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitLocal(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("local[index ").print(index()).print(']');
+    }
+
+    @Override
+    public Map<Object, Object> getDebugProperties() {
+        Map<Object, Object> properties = super.getDebugProperties();
+        properties.put("index", index());
+        return properties;
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        Local x = new Local(kind, index, into);
+        x.setDeclaredType(declaredType());
+        return x;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LocationNode.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,120 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ci.CiAddress.*;
+
+
+public final class LocationNode extends FloatingNode {
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_INDEX = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    public static final Object FINAL_LOCATION = new Object();
+
+    public static Object getArrayLocation(CiKind elementKind) {
+        return elementKind;
+    }
+
+    private int displacement;
+    private CiKind valueKind;
+    private Object locationIdentity;
+
+    public int displacement() {
+        return displacement;
+    }
+
+    public Value index() {
+        return (Value) inputs().get(super.inputCount() + INPUT_INDEX);
+    }
+
+    public void setIndex(Value index) {
+        inputs().set(super.inputCount() + INPUT_INDEX, index);
+    }
+
+    public static LocationNode create(Object identity, CiKind kind, int displacement, Graph graph) {
+        LocationNode result = new LocationNode(identity, kind, displacement, graph);
+        return graph.ideal(result);
+    }
+
+    private LocationNode(Object identity, CiKind kind, int displacement, Graph graph) {
+        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.displacement = displacement;
+        this.valueKind = kind;
+        this.locationIdentity = identity;
+    }
+
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return null;
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("mem location disp is ").print(displacement);
+    }
+
+    public CiKind getValueKind() {
+        return valueKind;
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new LocationNode(locationIdentity, valueKind, displacement, into);
+    }
+
+    public CiValue createAddress(LIRGenerator lirGenerator, Value object) {
+        CiValue indexValue = CiValue.IllegalValue;
+        Scale indexScale = Scale.Times1;
+        if (this.index() != null) {
+            indexValue = lirGenerator.load(this.index());
+            indexScale = Scale.fromInt(valueKind.sizeInBytes(lirGenerator.target().wordSize));
+        }
+        return new CiAddress(valueKind, lirGenerator.load(object), indexValue, indexScale, displacement);
+    }
+
+    public Object locationIdentity() {
+        return locationIdentity;
+    }
+
+    @Override
+    public boolean valueEqual(Node i) {
+        if (i instanceof LocationNode) {
+            LocationNode locationNode = (LocationNode) i;
+            return locationNode.locationIdentity == locationIdentity && locationNode.displacement == displacement;
+        }
+        return false;
+    }
+
+    @Override
+    public int valueNumber() {
+        return locationIdentity.hashCode() + displacement;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Logic.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code LogicOp} class definition.
+ */
+public abstract class Logic extends Binary {
+
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    /**
+     * Constructs a new logic operation instruction.
+     * @param opcode the opcode of the logic operation
+     * @param x the first input into this instruction
+     * @param y the second input into this instruction
+     */
+    public Logic(CiKind kind, int opcode, Value x, Value y, Graph graph) {
+        super(kind, opcode, x, y, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitLogic(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(x()).print(' ').print(this.shortName()).print(' ').print(y());
+    }
+
+    @Override
+    public abstract String shortName();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LookupSwitch.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import static com.oracle.max.graal.compiler.debug.InstructionPrinter.InstructionLineColumn.*;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+
+/**
+ * The {@code LookupSwitch} instruction represents a lookup switch bytecode, which has a sorted
+ * array of key values.
+ */
+public final class LookupSwitch extends Switch {
+
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    final int[] keys;
+
+    /**
+     * Constructs a new LookupSwitch instruction.
+     * @param value the instruction producing the value being switched on
+     * @param successors the list of successors
+     * @param keys the list of keys, sorted
+     * @param stateAfter the state after the switch
+     * @param graph
+     */
+    public LookupSwitch(Value value, List<? extends FixedNode> successors, int[] keys, double[] probability, Graph graph) {
+        super(value, successors, probability, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.keys = keys;
+    }
+
+    /**
+     * Gets the key at the specified index.
+     * @param i the index
+     * @return the key at that index
+     */
+    public int keyAt(int i) {
+        return keys[i];
+    }
+
+    public int keysLength() {
+        return keys.length;
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitLookupSwitch(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("lookupswitch ");
+        out.println(value());
+        int l = numberOfCases();
+        for (int i = 0; i < l; i++) {
+            INSTRUCTION.advance(out);
+            out.printf("case %5d: B%d%n", keyAt(i), blockSuccessor(i));
+        }
+        INSTRUCTION.advance(out);
+        out.print("default   : ").print(defaultSuccessor());
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        LookupSwitch x = new LookupSwitch(null, Arrays.asList(new FixedNodeWithNext[numberOfCases() + 1]), keys.clone(), branchProbability.clone(), into);
+        super.copyInto(x);
+        return x;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoopBegin.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,156 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.graph.*;
+
+public class LoopBegin extends Merge {
+
+    private double loopFrequency;
+
+    public LoopBegin(Graph graph) {
+        super(graph);
+        loopFrequency = 1;
+    }
+
+    public double loopFrequency() {
+        return loopFrequency;
+    }
+
+    public void setLoopFrequency(double loopFrequency) {
+        this.loopFrequency = loopFrequency;
+    }
+
+    public LoopEnd loopEnd() {
+        for (Node usage : usages()) {
+            if (usage instanceof LoopEnd) {
+                LoopEnd end = (LoopEnd) usage;
+                if (end.loopBegin() == this) {
+                    return end;
+                }
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitLoopBegin(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("loopBegin");
+    }
+
+    @Override
+    public String shortName() {
+        return "LoopBegin";
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        LoopBegin x = new LoopBegin(into);
+        x.setLoopFrequency(loopFrequency);
+        super.copyInto(x);
+        return x;
+    }
+
+    @Override
+    public int phiPredecessorCount() {
+        return 2;
+    }
+
+    @Override
+    public int phiPredecessorIndex(Node pred) {
+        if (pred == forwardEdge()) {
+            return 0;
+        } else if (pred == this.loopEnd()) {
+            return 1;
+        }
+        throw Util.shouldNotReachHere("unknown pred : " + pred + "(sp=" + forwardEdge() + ", le=" + this.loopEnd() + ")");
+    }
+
+    @Override
+    public Node phiPredecessorAt(int index) {
+        if (index == 0) {
+            return forwardEdge();
+        } else if (index == 1) {
+            return loopEnd();
+        }
+        throw Util.shouldNotReachHere();
+    }
+
+    public Collection<LoopCounter> counters() {
+        return Util.filter(this.usages(), LoopCounter.class);
+    }
+
+    @Override
+    public List<Node> phiPredecessors() {
+        return Arrays.asList(new Node[]{this.forwardEdge(), this.loopEnd()});
+    }
+
+    public EndNode forwardEdge() {
+        return this.endAt(0);
+    }
+
+    @Override
+    public boolean verify() {
+        assertTrue(loopEnd() != null);
+        assertTrue(forwardEdge() != null);
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "LoopBegin: " + super.toString();
+    }
+
+    @Override
+    public Node singlePredecessor() {
+        assert endCount() == 1;
+        return endAt(0).singlePredecessor();
+    }
+
+    @Override
+    public Iterable< ? extends Node> dataUsages() {
+        final Iterator< ? extends Node> dataUsages = super.dataUsages().iterator();
+        return new Iterable<Node>() {
+            @Override
+            public Iterator<Node> iterator() {
+                return new StateSplit.FilteringIterator(dataUsages, LoopBegin.class);
+            }
+        };
+    }
+
+    @Override
+    public Map<Object, Object> getDebugProperties() {
+        Map<Object, Object> properties = super.getDebugProperties();
+        properties.put("loopFrequency", String.format("%7.1f", loopFrequency));
+        return properties;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoopCounter.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,97 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class LoopCounter extends FloatingNode {
+
+    private static final int INPUT_COUNT = 3;
+    private static final int INPUT_MERGE = 0;
+    private static final int INPUT_INIT = 1;
+    private static final int INPUT_STRIDE = 2;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    public LoopCounter(CiKind kind, Value init, Value stride, LoopBegin loop, Graph graph) {
+        super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        setInit(init);
+        setStride(stride);
+        setLoopBegin(loop);
+    }
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    public Value init() {
+        return (Value) inputs().get(super.inputCount() + INPUT_INIT);
+    }
+
+    public Value setInit(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_INIT, n);
+    }
+
+    public Value stride() {
+        return (Value) inputs().get(super.inputCount() + INPUT_STRIDE);
+    }
+
+    public Value setStride(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_STRIDE, n);
+    }
+
+    public LoopBegin loopBegin() {
+        return (LoopBegin) inputs().get(super.inputCount() + INPUT_MERGE);
+    }
+
+    public Value setLoopBegin(LoopBegin n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_MERGE, n);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("loopcounter [").print(init()).print(",+").print(stride()).print("]");
+
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new LoopCounter(kind, null, null, null, into);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoopEnd.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,95 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public class LoopEnd extends FixedNode {
+
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_LOOP_BEGIN = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The instruction which produces the input value to this instruction.
+     */
+     public LoopBegin loopBegin() {
+        return (LoopBegin) inputs().get(super.inputCount() + INPUT_LOOP_BEGIN);
+    }
+
+    public LoopBegin setLoopBegin(LoopBegin n) {
+        return (LoopBegin) inputs().set(super.inputCount() + INPUT_LOOP_BEGIN, n);
+    }
+
+    public LoopEnd(Graph graph) {
+        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitLoopEnd(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("loopEnd ").print(loopBegin());
+    }
+
+    @Override
+    public String shortName() {
+        return "LoopEnd";
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        LoopEnd x = new LoopEnd(into);
+        super.copyInto(x);
+        return x;
+    }
+
+    @Override
+    public String toString() {
+        return "LoopEnd:" + super.toString();
+    }
+
+    @Override
+    public Iterable< ? extends Node> dataInputs() {
+        return Collections.emptyList();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MaterializeNode.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.asm.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.compiler.lir.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+public final class MaterializeNode extends FloatingNode {
+
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_VALUE = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The instruction which produces the input value to this instruction.
+     */
+     public Value value() {
+        return (Value) inputs().get(super.inputCount() + INPUT_VALUE);
+    }
+
+    public void setValue(Value n) {
+        inputs().set(super.inputCount() + INPUT_VALUE, n);
+    }
+
+    public MaterializeNode(Value value, Graph graph) {
+        super(CiKind.Int, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        setValue(value);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+    }
+
+    @Override
+    public boolean valueEqual(Node i) {
+        return (i instanceof MaterializeNode);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return (T) LIR_GENERATOR_OP;
+        }
+        return super.lookup(clazz);
+    }
+
+    public static final LIRGenerator.LIRGeneratorOp LIR_GENERATOR_OP = new LIRGenerator.LIRGeneratorOp() {
+
+        @Override
+        public void generate(Node n, LIRGenerator generator) {
+            LIRBlock trueSuccessor = new LIRBlock(new Label(), null);
+            generator.emitBooleanBranch(((MaterializeNode) n).value(), trueSuccessor, null, null);
+            CiValue result = generator.createResultVariable((Value) n);
+            LIRList lir = generator.lir();
+            lir.move(CiConstant.FALSE, result);
+            Label label = new Label();
+            lir.branch(Condition.TRUE, label);
+            lir.branchDestination(trueSuccessor.label);
+            lir.move(CiConstant.TRUE, result);
+            lir.branchDestination(label);
+        }
+    };
+
+    @Override
+    public void print(LogStream out) {
+        out.print("materialize(").print(value().toString()).print(')');
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new MaterializeNode(null, into);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Merge.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,346 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.compiler.value.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+/**
+ * Denotes the beginning of a basic block, and holds information
+ * about the basic block, including the successor and
+ * predecessor blocks, exception handlers, liveness information, etc.
+ */
+public class Merge extends StateSplit{
+
+    private static final int INPUT_COUNT = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    @Override
+    public boolean needsStateAfter() {
+        return false;
+    }
+
+    /**
+     * Constructs a new Merge at the specified bytecode index.
+     * @param bci the bytecode index of the start
+     * @param blockID the ID of the block
+     * @param graph
+     */
+    public Merge(Graph graph) {
+        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+    }
+
+    protected Merge(int inputCount, int successorCount, Graph graph) {
+        super(CiKind.Illegal, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitMerge(this);
+    }
+
+    public int endIndex(EndNode end) {
+        assert variableInputs().contains(end);
+        return variableInputs().indexOf(end);
+    }
+
+    public void addEnd(EndNode end) {
+        variableInputs().add(end);
+    }
+
+    public int endCount() {
+        return variableInputs().size();
+    }
+
+    public EndNode endAt(int index) {
+        return (EndNode) variableInputs().get(index);
+    }
+
+    @Override
+    public Iterable<EndNode> cfgPredecessors() {
+        return new Iterable<EndNode>() {
+            @Override
+            public Iterator<EndNode> iterator() {
+                return new Iterator<EndNode>() {
+                    int i = 0;
+                    @Override
+                    public void remove() {
+                        throw new UnsupportedOperationException();
+                    }
+                    @Override
+                    public EndNode next() {
+                        return Merge.this.endAt(i++);
+                    }
+                    @Override
+                    public boolean hasNext() {
+                        return i < Merge.this.endCount();
+                    }
+                };
+            }
+        };
+    }
+
+    @Override
+    public Iterable< ? extends Node> dataInputs() {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("merge #");
+        builder.append(id());
+        builder.append(" [");
+
+        builder.append("]");
+
+        builder.append(" -> ");
+        boolean hasSucc = false;
+        for (Node s : this.successors()) {
+            if (hasSucc) {
+                builder.append(", ");
+            }
+            builder.append("#");
+            if (s != null) {
+                builder.append(s.id());
+            } else {
+                builder.append("null");
+            }
+            hasSucc = true;
+        }
+        return builder.toString();
+    }
+
+    public void printWithoutPhis(LogStream out) {
+        // print block id
+        out.print("B").print(id()).print(" ");
+
+        // print flags
+        StringBuilder sb = new StringBuilder(8);
+        if (sb.length() != 0) {
+            out.print('(').print(sb.toString()).print(')');
+        }
+
+        // print block bci range
+        out.print('[').print(-1).print(", ").print(-1).print(']');
+
+        // print block successors
+        //if (end != null && end.blockSuccessors().size() > 0) {
+            out.print(" .");
+            for (Node successor : this.successors()) {
+                if (successor instanceof Value) {
+                    out.print((Value) successor);
+                } else {
+                    out.print(successor.toString());
+                }
+            }
+        //}
+
+        // print predecessors
+//        if (!blockPredecessors().isEmpty()) {
+//            out.print(" pred:");
+//            for (Instruction pred : blockPredecessors()) {
+//                out.print(pred.block());
+//            }
+//        }
+    }
+
+    @Override
+    public void print(LogStream out) {
+
+        printWithoutPhis(out);
+
+        // print phi functions
+        boolean hasPhisInLocals = false;
+        boolean hasPhisOnStack = false;
+
+        //if (end() != null && end().stateAfter() != null) {
+            FrameState state = stateAfter();
+
+            int i = 0;
+            while (!hasPhisOnStack && i < state.stackSize()) {
+                Value value = state.stackAt(i);
+                hasPhisOnStack = isPhiAtBlock(value);
+                if (value != null) {
+                    i += value.kind.sizeInSlots();
+                } else {
+                    i++;
+                }
+            }
+
+            for (i = 0; !hasPhisInLocals && i < state.localsSize();) {
+                Value value = state.localAt(i);
+                hasPhisInLocals = isPhiAtBlock(value);
+                // also ignore illegal HiWords
+                if (value != null) {
+                    i += value.kind.sizeInSlots();
+                } else {
+                    i++;
+                }
+            }
+        //}
+
+        // print values in locals
+        if (hasPhisInLocals) {
+            out.println();
+            out.println("Locals:");
+
+            int j = 0;
+            while (j < state.localsSize()) {
+                Value value = state.localAt(j);
+                if (value != null) {
+                    out.println(stateString(j, value));
+                    // also ignore illegal HiWords
+                    j += value.kind.sizeInSlots();
+                } else {
+                    j++;
+                }
+            }
+            out.println();
+        }
+
+        // print values on stack
+        if (hasPhisOnStack) {
+            out.println();
+            out.println("Stack:");
+            int j = 0;
+            while (j < stateAfter().stackSize()) {
+                Value value = stateAfter().stackAt(j);
+                if (value != null) {
+                    out.println(stateString(j, value));
+                    j += value.kind.sizeInSlots();
+                } else {
+                    j++;
+                }
+            }
+        }
+
+    }
+
+    /**
+     * Determines if a given instruction is a phi whose {@linkplain Phi#merge() join block} is a given block.
+     *
+     * @param value the instruction to test
+     * @param block the block that may be the join block of {@code value} if {@code value} is a phi
+     * @return {@code true} if {@code value} is a phi and its join block is {@code block}
+     */
+    private boolean isPhiAtBlock(Value value) {
+        return value instanceof Phi && ((Phi) value).merge() == this;
+    }
+
+
+    /**
+     * Formats a given instruction as a value in a {@linkplain FrameState frame state}. If the instruction is a phi defined at a given
+     * block, its {@linkplain Phi#valueCount() inputs} are appended to the returned string.
+     *
+     * @param index the index of the value in the frame state
+     * @param value the frame state value
+     * @param block if {@code value} is a phi, then its inputs are formatted if {@code block} is its
+     *            {@linkplain Phi#merge() join point}
+     * @return the instruction representation as a string
+     */
+    public String stateString(int index, Value value) {
+        StringBuilder sb = new StringBuilder(30);
+        sb.append(String.format("%2d  %s", index, Util.valueString(value)));
+        if (value instanceof Phi) {
+            Phi phi = (Phi) value;
+            // print phi operands
+            if (phi.merge() == this) {
+                sb.append(" [");
+                for (int j = 0; j < phi.valueCount(); j++) {
+                    sb.append(' ');
+                    Value operand = phi.valueAt(j);
+                    if (operand != null) {
+                        sb.append(Util.valueString(operand));
+                    } else {
+                        sb.append("NULL");
+                    }
+                }
+                sb.append("] ");
+            }
+        }
+        return sb.toString();
+    }
+
+    @Override
+    public String shortName() {
+        return "Merge #" + id();
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        assert getClass() == Merge.class : "copy of " + getClass();
+        Merge x = new Merge(into);
+        super.copyInto(x);
+        return x;
+    }
+
+    public void removeEnd(EndNode pred) {
+        int predIndex = variableInputs().indexOf(pred);
+        assert predIndex != -1;
+        variableInputs().remove(predIndex);
+
+        for (Node usage : usages()) {
+            if (usage instanceof Phi) {
+                ((Phi) usage).removeInput(predIndex);
+            }
+        }
+    }
+
+    public int phiPredecessorCount() {
+        return endCount();
+    }
+
+    public int phiPredecessorIndex(Node pred) {
+        EndNode end = (EndNode) pred;
+        return endIndex(end);
+    }
+
+    public Node phiPredecessorAt(int index) {
+        return endAt(index);
+    }
+
+    public Collection<Phi> phis() {
+        return Util.filter(this.usages(), Phi.class);
+    }
+
+    public List<Node> phiPredecessors() {
+        return Collections.unmodifiableList(variableInputs());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MonitorAddress.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+/**
+ * Instruction that is used to refer to the address of an on-stack monitor.
+ */
+public final class MonitorAddress extends Value {
+
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    private int monitorIndex;
+
+    public MonitorAddress(int monitorIndex, Graph graph) {
+        super(CiKind.Word, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.monitorIndex = monitorIndex;
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitMonitorAddress(this);
+    }
+
+    public int monitorIndex() {
+        return monitorIndex;
+    }
+
+    public void setMonitorIndex(int monitorIndex) {
+        this.monitorIndex = monitorIndex;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("monitor_address (").print(monitorIndex()).print(")");
+    }
+
+
+
+    @Override
+    public Map<Object, Object> getDebugProperties() {
+        Map<Object, Object> properties = super.getDebugProperties();
+        properties.put("monitorIndex", monitorIndex);
+        return properties;
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        MonitorAddress x = new MonitorAddress(monitorIndex, into);
+        return x;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MonitorEnter.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+
+/**
+ * The {@code MonitorEnter} instruction represents the acquisition of a monitor.
+ */
+public final class MonitorEnter extends AccessMonitor {
+
+    private static final int INPUT_COUNT = 0;
+
+    private static final int SUCCESSOR_COUNT = 1;
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * Creates a new MonitorEnter instruction.
+     *
+     * @param object the instruction producing the object
+     * @param lockAddress the address of the on-stack lock object or {@code null} if the runtime does not place locks on the stack
+     * @param lockNumber the number of the lock
+     * @param graph
+     */
+    public MonitorEnter(Value object, Value lockAddress, int lockNumber, Graph graph) {
+        super(object, lockAddress, lockNumber, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitMonitorEnter(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("enter monitor[").print(lockNumber).print("](").print(object()).print(')');
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        MonitorEnter x = new MonitorEnter(null, null, lockNumber, into);
+        super.copyInto(x);
+        return x;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MonitorExit.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+
+/**
+ * The {@code MonitorExit} instruction represents a monitor release.
+ */
+public final class MonitorExit extends AccessMonitor {
+
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    /**
+     * Creates a new MonitorExit instruction.
+     *
+     * @param object the instruction produces the object value
+     * @param lockAddress the address of the on-stack lock object or {@code null} if the runtime does not place locks on the stack
+     * @param lockNumber the number of the lock
+     * @param graph
+     */
+    public MonitorExit(Value object, Value lockAddress, int lockNumber, Graph graph) {
+        super(object, lockAddress, lockNumber, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitMonitorExit(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("exit monitor[").print(lockNumber).print("](").print(object()).print(')');
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        MonitorExit x = new MonitorExit(null, null, lockNumber, into);
+        super.copyInto(x);
+        return x;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Negate.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code NegateOp} instruction negates its operand.
+ */
+public final class Negate extends FloatingNode {
+    private static final NegateCanonicalizerOp CANONICALIZER = new NegateCanonicalizerOp();
+
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_X = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The instruction producing input to this instruction.
+     */
+     public Value x() {
+        return (Value) inputs().get(super.inputCount() + INPUT_X);
+    }
+
+    public Value setX(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_X, n);
+    }
+
+    /**
+     * Creates new NegateOp instance.
+     * @param x the instruction producing the value that is input to this instruction
+     */
+    public Negate(Value x, Graph graph) {
+        super(x.kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        setX(x);
+    }
+
+    // for copying
+    private Negate(CiKind kind, Graph graph) {
+        super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitNegate(this);
+    }
+
+    @Override
+    public int valueNumber() {
+        return Util.hash1(Bytecodes.INEG, x());
+    }
+
+    @Override
+    public boolean valueEqual(Node i) {
+        if (i instanceof Negate) {
+            Negate o = (Negate) i;
+            return x() == o.x();
+        }
+        return false;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("- ").print(x());
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        Negate x = new Negate(kind, into);
+        return x;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static class NegateCanonicalizerOp implements CanonicalizerOp {
+        @Override
+        public Node canonical(Node node) {
+            Negate negate = (Negate) node;
+            Value x = negate.x();
+            Graph graph = negate.graph();
+            if (x.isConstant()) {
+                switch (x.kind) {
+                    case Int: return Constant.forInt(-x.asConstant().asInt(), graph);
+                    case Long: return Constant.forLong(-x.asConstant().asLong(), graph);
+                    case Float: return Constant.forFloat(-x.asConstant().asFloat(), graph);
+                    case Double: return Constant.forDouble(-x.asConstant().asDouble(), graph);
+                }
+            }
+            if (x instanceof Negate && (x.kind == CiKind.Int || x.kind == CiKind.Long)) {
+                return ((Negate) x).x();
+            }
+            return negate;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NegateBooleanNode.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+public final class NegateBooleanNode extends BooleanNode {
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_NODE = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The instruction that produces the array object.
+     */
+     public Value value() {
+        return (Value) inputs().get(super.inputCount() + INPUT_NODE);
+    }
+
+    public Value setValue(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_NODE, n);
+    }
+
+    public NegateBooleanNode(Value value, Graph graph) {
+        super(CiKind.Int, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        setValue(value);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+    }
+
+    @Override
+    public boolean valueEqual(Node i) {
+        return i instanceof NegateBooleanNode;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(value()).print("!");
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new NegateBooleanNode(null, into);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static final CanonicalizerOp CANONICALIZER = new CanonicalizerOp() {
+        @Override
+        public Node canonical(Node node) {
+            NegateBooleanNode negateNode = (NegateBooleanNode) node;
+            Value value = negateNode.value();
+            if (value instanceof NegateBooleanNode) {
+                return ((NegateBooleanNode) value).value();
+            } else if (value instanceof Constant) {
+                return Constant.forBoolean(!value.asConstant().asBoolean(), node.graph());
+            }
+            return negateNode;
+        }
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewArray.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.phases.EscapeAnalysisPhase.EscapeField;
+import com.oracle.max.graal.compiler.phases.EscapeAnalysisPhase.EscapeOp;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code NewArray} class is the base of all instructions that allocate arrays.
+ */
+public abstract class NewArray extends FixedNodeWithNext {
+
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_LENGTH = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The instruction that produces the length of this array.
+     */
+     public Value length() {
+        return (Value) inputs().get(super.inputCount() + INPUT_LENGTH);
+    }
+
+    public Value setLength(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_LENGTH, n);
+    }
+
+    /**
+     * Constructs a new NewArray instruction.
+     * @param length the instruction that produces the length for this allocation
+     * @param inputCount
+     * @param successorCount
+     * @param graph
+     */
+    NewArray(Value length, int inputCount, int successorCount, Graph graph) {
+        super(CiKind.Object, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+        setLength(length);
+    }
+
+    /**
+     * The list of instructions which produce input for this instruction.
+     */
+    public Value dimension(int index) {
+        assert index == 0;
+        return length();
+    }
+
+    /**
+     * The rank of the array allocated by this instruction, i.e. how many array dimensions.
+     */
+    public int dimensionCount() {
+        return 1;
+    }
+
+    public abstract CiKind elementKind();
+
+    @Override
+    public Map<Object, Object> getDebugProperties() {
+        Map<Object, Object> properties = super.getDebugProperties();
+        properties.put("exactType", exactType());
+        return properties;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == EscapeOp.class) {
+            return (T) ESCAPE;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static final EscapeOp ESCAPE = new EscapeOp() {
+
+        @Override
+        public boolean canAnalyze(Node node) {
+            NewArray x = (NewArray) node;
+            CiConstant length = x.dimension(0).asConstant();
+            return length != null && length.asInt() >= 0 && length.asInt() < GraalOptions.MaximumEscapeAnalysisArrayLength;
+        }
+
+        @Override
+        public boolean escape(Node node, Node usage) {
+            if (usage instanceof LoadIndexed) {
+                LoadIndexed x = (LoadIndexed) usage;
+                assert x.array() == node;
+                CiConstant index = x.index().asConstant();
+                CiConstant length = ((NewArray) node).dimension(0).asConstant();
+                if (index == null || length == null || index.asInt() < 0 || index.asInt() >= length.asInt()) {
+                    return true;
+                }
+                return false;
+            } else if (usage instanceof StoreField) {
+                StoreField x = (StoreField) usage;
+                assert x.value() == node;
+                return true;
+            } else if (usage instanceof StoreIndexed) {
+                StoreIndexed x = (StoreIndexed) usage;
+                CiConstant index = x.index().asConstant();
+                CiConstant length = ((NewArray) node).dimension(0).asConstant();
+                if (index == null || length == null || index.asInt() < 0 || index.asInt() >= length.asInt()) {
+                    return true;
+                }
+                return x.value() == node && x.array() != node;
+            } else if (usage instanceof ArrayLength) {
+                ArrayLength x = (ArrayLength) usage;
+                assert x.array() == node;
+                return false;
+            } else if (usage instanceof VirtualObjectField) {
+                return false;
+            } else {
+                return super.escape(node, usage);
+            }
+        }
+
+        @Override
+        public EscapeField[] fields(Node node) {
+            NewArray x = (NewArray) node;
+            int length = x.dimension(0).asConstant().asInt();
+            EscapeField[] fields = new EscapeField[length];
+            for (int i = 0; i < length; i++) {
+                Integer representation = i;
+                fields[i] = new EscapeField("[" + i + "]", representation, ((NewArray) node).elementKind());
+            }
+            return fields;
+        }
+
+        @Override
+        public void beforeUpdate(Node node, Node usage) {
+            if (usage instanceof ArrayLength) {
+                ArrayLength x = (ArrayLength) usage;
+                x.replaceAndDelete(((NewArray) node).dimension(0));
+            } else {
+                super.beforeUpdate(node, usage);
+            }
+        }
+
+        @Override
+        public int updateState(Node node, Node current, Map<Object, Integer> fieldIndex, Value[] fieldState) {
+            if (current instanceof AccessIndexed) {
+                AccessIndexed x = (AccessIndexed) current;
+                if (x.array() == node) {
+                    int index = ((AccessIndexed) current).index().asConstant().asInt();
+                    if (current instanceof LoadIndexed) {
+                        x.replaceAtUsages(fieldState[index]);
+                        assert x.usages().size() == 0;
+                        x.replaceAndDelete(x.next());
+                    } else if (current instanceof StoreIndexed) {
+                        fieldState[index] = ((StoreIndexed) x).value();
+                        assert x.usages().size() == 0;
+                        x.replaceAndDelete(x.next());
+                        return index;
+                    }
+                }
+            }
+            return -1;
+        }
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewInstance.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.phases.EscapeAnalysisPhase.EscapeField;
+import com.oracle.max.graal.compiler.phases.EscapeAnalysisPhase.EscapeOp;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code NewInstance} instruction represents the allocation of an instance class object.
+ */
+public final class NewInstance extends FixedNodeWithNext {
+
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    final RiType instanceClass;
+    public final int cpi;
+    public final RiConstantPool constantPool;
+
+    /**
+     * Constructs a NewInstance instruction.
+     * @param type the class being allocated
+     * @param cpi the constant pool index
+     * @param graph
+     */
+    public NewInstance(RiType type, int cpi, RiConstantPool constantPool, Graph graph) {
+        super(CiKind.Object, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.instanceClass = type;
+        this.cpi = cpi;
+        this.constantPool = constantPool;
+    }
+
+    /**
+     * Gets the instance class being allocated by this instruction.
+     * @return the instance class allocated
+     */
+    public RiType instanceClass() {
+        return instanceClass;
+    }
+
+    /**
+     * Gets the exact type produced by this instruction. For allocations of instance classes, this is
+     * always the class allocated.
+     * @return the exact type produced by this instruction
+     */
+    @Override
+    public RiType exactType() {
+        return instanceClass;
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitNewInstance(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("new instance ").print(CiUtil.toJavaName(instanceClass()));
+    }
+
+    @Override
+    public Map<Object, Object> getDebugProperties() {
+        Map<Object, Object> properties = super.getDebugProperties();
+        properties.put("instanceClass", instanceClass);
+        properties.put("cpi", cpi);
+        return properties;
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        NewInstance x = new NewInstance(instanceClass, cpi, constantPool, into);
+        super.copyInto(x);
+        return x;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == EscapeOp.class) {
+            return (T) ESCAPE;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static final EscapeOp ESCAPE = new EscapeOp() {
+
+        @Override
+        public boolean canAnalyze(Node node) {
+            return ((NewInstance) node).instanceClass().isResolved();
+        }
+
+        @Override
+        public boolean escape(Node node, Node usage) {
+            if (usage instanceof LoadField) {
+                LoadField x = (LoadField) usage;
+                assert x.object() == node;
+                return x.field().isResolved() == false;
+            } else if (usage instanceof StoreField) {
+                StoreField x = (StoreField) usage;
+                return x.value() == node && x.object() != node;
+            } else if (usage instanceof StoreIndexed) {
+                StoreIndexed x = (StoreIndexed) usage;
+                assert x.value() == node;
+                return true;
+            } else if (usage instanceof VirtualObjectField) {
+                return false;
+            } else if (usage instanceof RegisterFinalizer) {
+                RegisterFinalizer x = (RegisterFinalizer) usage;
+                assert x.object() == node;
+                return false;
+            } else {
+                return super.escape(node, usage);
+            }
+        }
+
+        @Override
+        public EscapeField[] fields(Node node) {
+            NewInstance x = (NewInstance) node;
+            RiField[] riFields = x.instanceClass().fields();
+            EscapeField[] fields = new EscapeField[riFields.length];
+            for (int i = 0; i < riFields.length; i++) {
+                RiField field = riFields[i];
+                fields[i] = new EscapeField(field.name(), field, field.kind().stackKind());
+            }
+            return fields;
+        }
+
+        @Override
+        public void beforeUpdate(Node node, Node usage) {
+            if (usage instanceof RegisterFinalizer) {
+                RegisterFinalizer x = (RegisterFinalizer) usage;
+                x.replaceAndDelete(x.next());
+            } else {
+                super.beforeUpdate(node, usage);
+            }
+        }
+
+        @Override
+        public int updateState(Node node, Node current, Map<Object, Integer> fieldIndex, Value[] fieldState) {
+            if (current instanceof AccessField) {
+                AccessField x = (AccessField) current;
+                if (x.object() == node) {
+                    int field = fieldIndex.get(((AccessField) current).field());
+                    if (current instanceof LoadField) {
+                        assert fieldState[field] != null : field + ", " + ((AccessField) current).field();
+                        x.replaceAtUsages(fieldState[field]);
+                        assert x.usages().size() == 0;
+                        x.replaceAndDelete(x.next());
+                    } else if (current instanceof StoreField) {
+                        fieldState[field] = ((StoreField) x).value();
+                        assert x.usages().size() == 0;
+                        x.replaceAndDelete(x.next());
+                        return field;
+                    }
+                }
+            }
+            return -1;
+        }
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewMultiArray.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code NewMultiArray} instruction represents an allocation of a multi-dimensional object
+ * array.
+ */
+public final class NewMultiArray extends NewArray {
+
+    private final int dimensionCount;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + dimensionCount;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The list of instructions which produce input for this instruction.
+     */
+    @Override
+    public Value dimension(int index) {
+        assert index >= 0 && index < dimensionCount;
+        return (Value) inputs().get(super.inputCount() + index);
+    }
+
+    public Value setDimension(int index, Value n) {
+        assert index >= 0 && index < dimensionCount;
+        return (Value) inputs().set(super.inputCount() + index, n);
+    }
+
+    /**
+     * The rank of the array allocated by this instruction, i.e. how many array dimensions.
+     */
+    @Override
+    public int dimensionCount() {
+        return dimensionCount;
+    }
+
+    public final RiType elementType;
+    public final int cpi;
+    public final RiConstantPool constantPool;
+
+    /**
+     * Constructs a new NewMultiArray instruction.
+     * @param elementType the element type of the array
+     * @param dimensions the instructions which produce the dimensions for this array
+     * @param cpi the constant pool index for resolution
+     * @param riConstantPool the constant pool for resolution
+     * @param graph
+     */
+    public NewMultiArray(RiType elementType, Value[] dimensions, int cpi, RiConstantPool riConstantPool, Graph graph) {
+        super(null, dimensions.length, SUCCESSOR_COUNT, graph);
+        this.constantPool = riConstantPool;
+        this.elementType = elementType;
+        this.cpi = cpi;
+
+        this.dimensionCount = dimensions.length;
+        for (int i = 0; i < dimensions.length; i++) {
+            setDimension(i, dimensions[i]);
+        }
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitNewMultiArray(this);
+    }
+
+    /**
+     * Gets the element type of the array.
+     * @return the element type of the array
+     */
+    public RiType elementType() {
+        return elementType;
+    }
+
+    @Override
+    public CiKind elementKind() {
+        return elementType.kind();
+    }
+
+    @Override
+    public RiType exactType() {
+        return elementType.arrayOf();
+    }
+
+    @Override
+    public RiType declaredType() {
+        return exactType();
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("new multi array [");
+        for (int i = 0; i < dimensionCount; i++) {
+          if (i > 0) {
+              out.print(", ");
+          }
+          out.print(dimension(i));
+        }
+        out.print("] ").print(CiUtil.toJavaName(elementType));
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        NewMultiArray x = new NewMultiArray(elementType, new Value[dimensionCount], cpi, constantPool, into);
+        super.copyInto(x);
+        return x;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewObjectArray.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code NewObjectArray} instruction represents an allocation of an object array.
+ */
+public final class NewObjectArray extends NewArray {
+
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    final RiType elementClass;
+
+    /**
+     * Constructs a new NewObjectArray instruction.
+     * @param elementClass the class of elements in this array
+     * @param length the instruction producing the length of the array
+     * @param graph
+     */
+    public NewObjectArray(RiType elementClass, Value length, Graph graph) {
+        super(length, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.elementClass = elementClass;
+    }
+
+    /**
+     * Gets the type of the elements of the array.
+     * @return the element type of the array
+     */
+    public RiType elementType() {
+        return elementClass;
+    }
+
+    @Override
+    public CiKind elementKind() {
+        return elementClass.kind();
+    }
+
+    @Override
+    public RiType exactType() {
+        return elementClass.arrayOf();
+    }
+
+    @Override
+    public RiType declaredType() {
+        return exactType();
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitNewObjectArray(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("new object array [").print(length()).print("] ").print(CiUtil.toJavaName(elementType()));
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        NewObjectArray x = new NewObjectArray(elementClass, null, into);
+        super.copyInto(x);
+        return x;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewTypeArray.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code NewTypeArray} class definition.
+ */
+public final class NewTypeArray extends NewArray {
+
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    final RiType elementType;
+
+    public NewTypeArray(Value length, RiType elementType, Graph graph) {
+        super(length, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.elementType = elementType;
+    }
+
+    @Override
+    public CiKind elementKind() {
+        return elementType.kind();
+    }
+
+    @Override
+    public RiType declaredType() {
+        return elementType.arrayOf();
+    }
+
+    @Override
+    public RiType exactType() {
+        return elementType.arrayOf();
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitNewTypeArray(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("new ").print(elementKind().name()).print(" array [").print(length()).print(']');
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        NewTypeArray x = new NewTypeArray(null, elementType, into);
+        super.copyInto(x);
+        return x;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NormalizeCompare.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+/**
+ * Returns -1, 0, or 1 if either x > y, x == y, or x < y.
+ */
+public final class NormalizeCompare extends Binary {
+
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    /**
+     * Creates a new compare operation.
+     * @param opcode the bytecode opcode
+     * @param kind the result kind
+     * @param x the first input
+     * @param y the second input
+     */
+    public NormalizeCompare(int opcode, CiKind kind, Value x, Value y, Graph graph) {
+        super(kind, opcode, x, y, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitMaterialize(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(x()).
+            print(' ').
+            print(Bytecodes.operator(opcode)).
+            print(' ').
+            print(y());
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new NormalizeCompare(opcode, kind, null, null, into);
+    }
+
+    public boolean isUnorderedLess() {
+        return this.opcode == Bytecodes.FCMPL || this.opcode == Bytecodes.DCMPL;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Or.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,114 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+
+/**
+ *
+ */
+public final class Or extends Logic {
+    private static final OrCanonicalizerOp CANONICALIZER = new OrCanonicalizerOp();
+
+    /**
+     * @param opcode
+     * @param kind
+     * @param x
+     * @param y
+     * @param graph
+     */
+    public Or(CiKind kind, Value x, Value y, Graph graph) {
+        super(kind, kind == CiKind.Int ? Bytecodes.IOR : Bytecodes.LOR, x, y, graph);
+    }
+
+    @Override
+    public String shortName() {
+        return "|";
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new Or(kind, null, null, into);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static class OrCanonicalizerOp implements CanonicalizerOp {
+        @Override
+        public Node canonical(Node node) {
+            Or or = (Or) node;
+            CiKind kind = or.kind;
+            Graph graph = or.graph();
+            Value x = or.x();
+            Value y = or.y();
+            if (x == y) {
+                return x;
+            }
+            if (x.isConstant() && !y.isConstant()) {
+                or.swapOperands();
+                Value t = y;
+                y = x;
+                x = t;
+            }
+            if (x.isConstant()) {
+                if (kind == CiKind.Int) {
+                    return Constant.forInt(x.asConstant().asInt() | y.asConstant().asInt(), graph);
+                } else {
+                    assert kind == CiKind.Long;
+                    return Constant.forLong(x.asConstant().asLong() | y.asConstant().asLong(), graph);
+                }
+            } else if (y.isConstant()) {
+                if (kind == CiKind.Int) {
+                    int c = y.asConstant().asInt();
+                    if (c == -1) {
+                        return Constant.forInt(-1, graph);
+                    }
+                    if (c == 0) {
+                        return x;
+                    }
+                } else {
+                    assert kind == CiKind.Long;
+                    long c = y.asConstant().asLong();
+                    if (c == -1) {
+                        return Constant.forLong(-1, graph);
+                    }
+                    if (c == 0) {
+                        return x;
+                    }
+                }
+            }
+            return or;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Phi.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.ir.StateSplit.*;
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code Phi} instruction represents the merging of dataflow
+ * in the instruction graph. It refers to a join block and a variable.
+ */
+public final class Phi extends FloatingNode {
+
+    private static final int DEFAULT_MAX_VALUES = 2;
+
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_MERGE = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    private final PhiType type;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The merge node for this phi.
+     */
+    public Merge merge() {
+        return (Merge) inputs().get(super.inputCount() + INPUT_MERGE);
+    }
+
+    public void setMerge(Merge n) {
+        assert n != null;
+        inputs().set(super.inputCount() + INPUT_MERGE, n);
+    }
+
+    public static enum PhiType {
+        Value,          // normal value phis
+        Memory,         // memory phis
+        Virtual         // phis used for VirtualObjectField merges
+    }
+
+    public Phi(CiKind kind, Merge merge, PhiType type, Graph graph) {
+        super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.type = type;
+        setMerge(merge);
+    }
+
+    private Phi(CiKind kind, PhiType type, Graph graph) {
+        super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.type = type;
+    }
+
+    public PhiType type() {
+        return type;
+    }
+
+    @Override
+    public boolean verify() {
+        assertTrue(merge() != null);
+        assertTrue(merge().phiPredecessorCount() == valueCount(), merge().phiPredecessorCount() + "==" + valueCount());
+        return true;
+    }
+
+    /**
+     * Get the instruction that produces the value associated with the i'th predecessor
+     * of the join block.
+     * @param i the index of the predecessor
+     * @return the instruction that produced the value in the i'th predecessor
+     */
+    public Value valueAt(int i) {
+        return (Value) variableInputs().get(i);
+    }
+
+    public void setValueAt(int i, Value x) {
+        inputs().set(INPUT_COUNT + i, x);
+    }
+
+    /**
+     * Get the number of inputs to this phi (i.e. the number of predecessors to the join block).
+     * @return the number of inputs in this phi
+     */
+    public int valueCount() {
+        return variableInputs().size();
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitPhi(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("phi function (");
+        for (int i = 0; i < valueCount(); ++i) {
+            if (i != 0) {
+                out.print(' ');
+            }
+            out.print(valueAt(i));
+        }
+        out.print(')');
+    }
+
+    @Override
+    public String shortName() {
+        StringBuilder str = new StringBuilder();
+        for (int i = 0; i < valueCount(); ++i) {
+            if (i != 0) {
+                str.append(' ');
+            }
+            str.append(valueAt(i) == null ? "-" : valueAt(i).id());
+        }
+        if (type == PhiType.Value) {
+            return "Phi: (" + str + ")";
+        } else {
+            return type + "Phi: (" + str + ")";
+        }
+    }
+
+    public void addInput(Node y) {
+        variableInputs().add(y);
+    }
+
+    public void removeInput(int index) {
+        variableInputs().remove(index);
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        Phi x = new Phi(kind, type, into);
+        return x;
+    }
+
+    @Override
+    public Iterable<? extends Node> dataInputs() {
+        final Iterator< ? extends Node> input = super.dataInputs().iterator();
+        return new Iterable<Node>() {
+            @Override
+            public Iterator<Node> iterator() {
+                return new FilteringIterator(input, Merge.class);
+            }
+        };
+    }
+
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() {
+
+        @Override
+        public Node canonical(Node node) {
+            Phi phiNode = (Phi) node;
+//            if (phiNode.valueCount() != 2 || phiNode.merge().endCount() != 2 || phiNode.merge().phis().size() != 1) {
+//                return phiNode;
+//            }
+//            if (!(phiNode.valueAt(0) instanceof Constant && phiNode.valueAt(1) instanceof Constant)) {
+//                return phiNode;
+//            }
+//            Merge merge = phiNode.merge();
+//            Node end0 = merge.endAt(0);
+//            Node end1 = merge.endAt(1);
+//            if (end0.predecessors().size() != 1 || end1.predecessors().size() != 1) {
+//                return phiNode;
+//            }
+//            Node endPred0 = end0.predecessors().get(0);
+//            Node endPred1 = end1.predecessors().get(0);
+//            if (endPred0 != endPred1 || !(endPred0 instanceof If)) {
+//                return phiNode;
+//            }
+//            If ifNode = (If) endPred0;
+//            if (ifNode.predecessors().size() != 1) {
+//                return phiNode;
+//            }
+//            boolean inverted = ((If) endPred0).trueSuccessor() == end1;
+//            CiConstant trueValue = phiNode.valueAt(inverted ? 1 : 0).asConstant();
+//            CiConstant falseValue = phiNode.valueAt(inverted ? 0 : 1).asConstant();
+//            if (trueValue.kind != CiKind.Int || falseValue.kind != CiKind.Int) {
+//                return phiNode;
+//            }
+//            if ((trueValue.asInt() == 0 || trueValue.asInt() == 1) && (falseValue.asInt() == 0 || falseValue.asInt() == 1) && (trueValue.asInt() != falseValue.asInt())) {
+//                MaterializeNode result;
+//                if (trueValue.asInt() == 1) {
+//                    result = new MaterializeNode(ifNode.compare(), phiNode.graph());
+//                } else {
+//                    result = new MaterializeNode(new NegateBooleanNode(ifNode.compare(), phiNode.graph()), phiNode.graph());
+//                }
+//                Node next = merge.next();
+//                merge.setNext(null);
+//                ifNode.predecessors().get(0).successors().replace(ifNode, next);
+//                return result;
+//            }
+            return phiNode;
+        }
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Placeholder.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,71 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public class Placeholder extends StateSplit {
+
+    private static final int INPUT_COUNT = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    public Placeholder(Graph graph) {
+        super(CiKind.Void, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        //assert false;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        assert false;
+    }
+
+    @Override
+    public String shortName() {
+        return "Placeholder" + id();
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        Placeholder x = new Placeholder(into);
+        super.copyInto(x);
+        return x;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ReadNode.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class ReadNode extends AccessNode {
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+
+    public ReadNode(CiKind kind, Value object, LocationNode location, Graph graph) {
+        super(kind, object, location, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitMemoryRead(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("mem read from ").print(object());
+    }
+
+    @Override
+    public boolean valueEqual(Node i) {
+        return i instanceof ReadNode;
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        ReadNode x = new ReadNode(super.kind, null, null, into);
+        super.copyInto(x);
+        return x;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ReadVectorNode.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,67 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class ReadVectorNode extends AccessVectorNode {
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    public ReadVectorNode(AbstractVectorNode vector, Value object, LocationNode location, Graph graph) {
+        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, vector, object, location, graph);
+    }
+
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return null;
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        ReadVectorNode x = new ReadVectorNode(null, null, null, into);
+        super.copyInto(x);
+        return x;
+    }
+
+
+    @Override
+    public void addToLoop(LoopBegin loop, IdentityHashMap<AbstractVectorNode, Value> nodes) {
+        LocationNode newLocation = LocationNode.create(LocationNode.getArrayLocation(location().getValueKind()), location().getValueKind(), location().displacement(), graph());
+        Value index = nodes.get(vector());
+        assert index != null;
+        newLocation.setIndex(index);
+        ReadNode readNode = new ReadNode(location().getValueKind().stackKind(), object(), newLocation, graph());
+        loop.loopEnd().replaceAtPredecessors(readNode);
+        readNode.setNext(loop.loopEnd());
+        nodes.put(this, readNode);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/RegisterFinalizer.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.graph.*;
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * This instruction is used to perform the finalizer registration at the end of the java.lang.Object constructor.
+ */
+public final class RegisterFinalizer extends StateSplit {
+
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_OBJECT = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The instruction that produces the object whose finalizer should be registered.
+     */
+     public Value object() {
+        return (Value) inputs().get(super.inputCount() + INPUT_OBJECT);
+    }
+
+    public Value setObject(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_OBJECT, n);
+    }
+
+    public RegisterFinalizer(Value object, Graph graph) {
+        super(CiKind.Void, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        setObject(object);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitRegisterFinalizer(this);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static final CanonicalizerOp CANONICALIZER = new CanonicalizerOp() {
+
+        @Override
+        public Node canonical(Node node) {
+            RegisterFinalizer finalizer = (RegisterFinalizer) node;
+            Value object = finalizer.object();
+
+            RiType declaredType = object.declaredType();
+            RiType exactType = object.exactType();
+            if (exactType == null && declaredType != null) {
+                exactType = declaredType.exactType();
+            }
+
+            boolean needsCheck = true;
+            if (exactType != null) {
+                // we have an exact type
+                needsCheck = exactType.hasFinalizer();
+            } else {
+                // if either the declared type of receiver or the holder can be assumed to have no finalizers
+                if (declaredType != null && !declaredType.hasFinalizableSubclass()) {
+                    if (((CompilerGraph) node.graph()).assumptions().recordNoFinalizableSubclassAssumption(declaredType)) {
+                        needsCheck = false;
+                    }
+                }
+            }
+
+            if (needsCheck) {
+                if (GraalOptions.TraceCanonicalizer) {
+                    TTY.println("Could not canonicalize finalizer " + object + " (declaredType=" + declaredType + ", exactType=" + exactType + ")");
+                }
+            } else {
+                if (GraalOptions.TraceCanonicalizer) {
+                    TTY.println("Canonicalized finalizer for object " + object);
+                }
+                return finalizer.next();
+            }
+
+            return finalizer;
+        }
+    };
+
+    @Override
+    public void print(LogStream out) {
+        out.print("register finalizer ").print(object());
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        RegisterFinalizer x = new RegisterFinalizer(null, into);
+        super.copyInto(x);
+        return x;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Return.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code Return} class definition.
+ */
+public final class Return extends FixedNode {
+
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_RESULT = 0;
+
+    private static final int SUCCESSOR_COUNT = 1;
+    private static final int SUCCESSOR_END = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The instruction that produces the result for the return.
+     */
+     public Value result() {
+        return (Value) inputs().get(super.inputCount() + INPUT_RESULT);
+    }
+
+    public Value setResult(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_RESULT, n);
+    }
+
+    /**
+     * Constructs a new Return instruction.
+     * @param result the instruction producing the result for this return; {@code null} if this
+     * is a void return
+     * @param graph
+     */
+    public Return(Value result, Graph graph) {
+        super(result == null ? CiKind.Void : result.kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        setResult(result);
+    }
+
+    // for copying
+    private Return(CiKind kind, Graph graph) {
+        super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitReturn(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        if (result() == null) {
+            out.print("return");
+        } else {
+            out.print(kind.typeChar).print("return ").print(result());
+        }
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        Return x = new Return(kind, into);
+        super.copyInto(x);
+        return x;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/RightShift.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,108 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+
+public final class RightShift extends Shift {
+    private static final RighShiftCanonicalizerOp CANONICALIZER = new RighShiftCanonicalizerOp();
+
+    public RightShift(CiKind kind, Value x, Value y, Graph graph) {
+        super(kind, kind == CiKind.Int ? Bytecodes.ISHR : Bytecodes.LSHR, x, y, graph);
+    }
+
+    @Override
+    public String shortName() {
+        return ">>";
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        RightShift rs = new RightShift(kind, null, null, into);
+        return rs;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static class RighShiftCanonicalizerOp implements CanonicalizerOp {
+        @Override
+        public Node canonical(Node node) {
+            RightShift rightShift = (RightShift) node;
+            CiKind kind = rightShift.kind;
+            Graph graph = rightShift.graph();
+            Value value = rightShift.x();
+            Value y = rightShift.y();
+            if (y.isConstant()) {
+                int amount = y.asConstant().asInt();
+                int originalAmout = amount;
+                int mask;
+                if (kind == CiKind.Int) {
+                    mask = 0x1f;
+                } else {
+                    assert kind == CiKind.Long;
+                    mask = 0x3f;
+                }
+                amount &= mask;
+                if (value.isConstant()) {
+                    if (kind == CiKind.Int) {
+                        return Constant.forInt(value.asConstant().asInt() >> amount, graph);
+                    } else {
+                        assert kind == CiKind.Long;
+                        return Constant.forLong(value.asConstant().asLong() >> amount, graph);
+                    }
+                }
+                if (amount == 0) {
+                    return value;
+                }
+                if (value instanceof Shift) {
+                    Shift other = (Shift) value;
+                    if (other.y().isConstant()) {
+                        int otherAmount = other.y().asConstant().asInt() & mask;
+                        if (other instanceof RightShift) {
+                            int total = amount + otherAmount;
+                            if (total != (total & mask)) {
+                                return Constant.forInt(0, graph);
+                            }
+                            return new RightShift(kind, other.x(), Constant.forInt(total, graph), graph);
+                        }
+                    }
+                }
+                if (originalAmout != amount) {
+                    return new RightShift(kind, value, Constant.forInt(amount, graph), graph);
+                }
+            }
+            return rightShift;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Shift.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code ShiftOp} class represents shift operations.
+ */
+public abstract class Shift extends Binary {
+
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    /**
+     * Creates a new shift operation.
+     * @param opcode the opcode of the shift
+     * @param x the first input value
+     * @param s the second input value
+     */
+    public Shift(CiKind kind, int opcode, Value x, Value s, Graph graph) {
+        super(kind, opcode, x, s, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        assert x == null || x.kind == kind;
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitShift(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(x()).print(' ').print(this.shortName()).print(' ').print(y());
+    }
+
+    @Override
+    public abstract String shortName();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StateSplit.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.value.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code StateSplit} class is the abstract base class of all instructions
+ * that store an immutable copy of the frame state.
+ */
+public abstract class StateSplit extends FixedNodeWithNext {
+
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_STATE_AFTER = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The state for this instruction.
+     */
+    public FrameState stateAfter() {
+        return (FrameState) inputs().get(super.inputCount() + INPUT_STATE_AFTER);
+    }
+
+    public void setStateAfter(FrameState n) {
+        inputs().set(super.inputCount() + INPUT_STATE_AFTER, n);
+    }
+
+    /**
+     * Creates a new state split with the specified value type.
+     * @param kind the type of the value that this instruction produces
+     * @param inputCount
+     * @param successorCount
+     * @param graph
+     */
+    public StateSplit(CiKind kind, int inputCount, int successorCount, Graph graph) {
+        super(kind, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+    }
+
+    public boolean needsStateAfter() {
+        return true;
+    }
+
+    @Override
+    public void delete() {
+        FrameState stateAfter = stateAfter();
+        super.delete();
+        if (stateAfter != null) {
+            if (stateAfter.usages().isEmpty()) {
+                stateAfter.delete();
+            }
+        }
+    }
+
+    @Override
+    public Iterable< ? extends Node> dataInputs() {
+        final Iterator< ? extends Node> dataInputs = super.dataInputs().iterator();
+        return new Iterable<Node>() {
+            @Override
+            public Iterator<Node> iterator() {
+                return new FilteringIterator(dataInputs, FrameState.class);
+            }
+        };
+    }
+
+    public static final class FilteringIterator implements Iterator<Node> {
+
+        private final Iterator< ? extends Node> input;
+        private Node next;
+        private Class< ? > clazz;
+
+        public FilteringIterator(Iterator< ? extends Node> input, Class<?> clazz) {
+            this.input = input;
+            this.clazz = clazz;
+        }
+
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Node next() {
+            forward();
+            if (!hasNext()) {
+                throw new NoSuchElementException();
+            }
+            Node res = next;
+            next = null;
+            return res;
+        }
+
+        @Override
+        public boolean hasNext() {
+            forward();
+            return next != null;
+        }
+
+        private void forward() {
+            while (next == null && input.hasNext()) {
+                next = input.next();
+                if (clazz.isInstance(next)) {
+                    next = null;
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StoreField.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.phases.*;
+import com.oracle.max.graal.compiler.phases.LoweringPhase.LoweringOp;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code StoreField} instruction represents a write to a static or instance field.
+ */
+public final class StoreField extends AccessField {
+
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_VALUE = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The value that is written to the field.
+     */
+     public Value value() {
+        return (Value) inputs().get(super.inputCount() + INPUT_VALUE);
+    }
+
+    public Value setValue(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_VALUE, n);
+    }
+
+    /**
+     * Creates a new LoadField instance.
+     * @param object the receiver object
+     * @param field the compiler interface field
+     * @param value the instruction representing the value to store to the field
+     * @param stateAfter the state after the field access
+     * @param graph
+     */
+    public StoreField(Value object, RiField field, Value value, Graph graph) {
+        super(CiKind.Void, object, field, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        setValue(value);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitStoreField(this);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(java.lang.Class<T> clazz) {
+        if (clazz == LoweringOp.class) {
+            return (T) LoweringPhase.DELEGATE_TO_RUNTIME;
+        }
+        return super.lookup(clazz);
+    };
+
+    @Override
+    public void print(LogStream out) {
+        out.print(object()).
+        print(".").
+        print(field().name()).
+        print(" := ").
+        print(value()).
+        print(" [type: ").print(CiUtil.format("%h.%n:%t", field(), false)).
+        print(']');
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        StoreField x = new StoreField(null, field, null, into);
+        super.copyInto(x);
+        return x;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StoreIndexed.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.phases.*;
+import com.oracle.max.graal.compiler.phases.LoweringPhase.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code StoreIndexed} instruction represents a write to an array element.
+ */
+public final class StoreIndexed extends AccessIndexed {
+
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_VALUE = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The instruction that produces the value that is to be stored into the array.
+     */
+     public Value value() {
+        return (Value) inputs().get(super.inputCount() + INPUT_VALUE);
+    }
+
+    public Value setValue(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_VALUE, n);
+    }
+
+    /**
+     * Creates a new StoreIndexed instruction.
+     * @param array the instruction producing the array
+     * @param index the instruction producing the index
+     * @param length the instruction producing the length
+     * @param elementKind the element type
+     * @param value the value to store into the array
+     * @param stateAfter the state after executing this instruction
+     * @param graph
+     */
+    public StoreIndexed(Value array, Value index, Value length, CiKind elementKind, Value value, Graph graph) {
+        super(CiKind.Void, array, index, length, elementKind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        setValue(value);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitStoreIndexed(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(array()).print('[').print(index()).print("] := ").print(value()).print(" (").print(kind.typeChar).print(')');
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LoweringOp.class) {
+            return (T) LoweringPhase.DELEGATE_TO_RUNTIME;
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        StoreIndexed x = new StoreIndexed(null, null, null, elementKind(), null, into);
+        super.copyInto(x);
+        return x;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Switch.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code Switch} class is the base of both lookup and table switches.
+ */
+public abstract class Switch extends ControlSplit {
+
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_VALUE = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The instruction that provides the input value to this switch.
+     */
+     public Value value() {
+        return (Value) inputs().get(super.inputCount() + INPUT_VALUE);
+    }
+
+    public Value setValue(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_VALUE, n);
+    }
+
+    /**
+     * Constructs a new Switch.
+     * @param value the instruction that provides the value to be switched over
+     * @param successors the list of successors of this switch
+     * @param stateAfter the state after the switch
+     * @param graph
+     */
+    public Switch(Value value, List<? extends FixedNode> successors, double[] probability, int inputCount, int successorCount, Graph graph) {
+        super(CiKind.Illegal, successors, probability, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+        setValue(value);
+    }
+
+    /**
+     * Gets the number of cases that this switch covers (excluding the default case).
+     * @return the number of cases
+     */
+    public int numberOfCases() {
+        return blockSuccessorCount() - 1;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/TableSwitch.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import static com.oracle.max.graal.compiler.debug.InstructionPrinter.InstructionLineColumn.*;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+
+/**
+ * The {@code TableSwitch} instruction represents a table switch.
+ */
+public final class TableSwitch extends Switch {
+
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    final int lowKey;
+
+    /**
+     * Constructs a new TableSwitch instruction.
+     * @param value the instruction producing the value being switched on
+     * @param successors the list of successors
+     * @param lowKey the lowest integer key in the table
+     * @param stateAfter the state after the switch
+     * @param graph
+     */
+    public TableSwitch(Value value, List<? extends FixedNode> successors, int lowKey, double[] probability, Graph graph) {
+        super(value, successors, probability, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.lowKey = lowKey;
+    }
+
+    /**
+     * Gets the lowest key in the table switch (inclusive).
+     * @return the low key
+     */
+    public int lowKey() {
+        return lowKey;
+    }
+
+    /**
+     * Gets the highest key in the table switch (exclusive).
+     * @return the high key
+     */
+    public int highKey() {
+        return lowKey + numberOfCases();
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitTableSwitch(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("tableswitch ");
+        out.println(value());
+        int l = numberOfCases();
+        for (int i = 0; i < l; i++) {
+            INSTRUCTION.advance(out);
+            out.printf("case %5d: B%d%n", lowKey() + i, blockSuccessor(i));
+        }
+        INSTRUCTION.advance(out);
+        out.print("default   : ").print(defaultSuccessor());
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        TableSwitch x = new TableSwitch(null, Arrays.asList(new FixedNodeWithNext[numberOfCases() + 1]), lowKey, branchProbability, into);
+        super.copyInto(x);
+        return x;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/TypeCheck.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code TypeCheck} instruction is the base class of casts and instanceof tests.
+ */
+public abstract class TypeCheck extends BooleanNode {
+
+    private static final int INPUT_COUNT = 2;
+    private static final int INPUT_OBJECT = 0;
+    private static final int INPUT_TARGET_CLASS_INSTRUCTION = 1;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The instruction which produces the object input.
+     */
+     public Value object() {
+        return (Value) inputs().get(super.inputCount() + INPUT_OBJECT);
+    }
+
+    public Value setObject(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_OBJECT, n);
+    }
+
+    /**
+     * The instruction that loads the target class object that is used by this checkcast.
+     */
+     public Value targetClassInstruction() {
+        return (Value) inputs().get(super.inputCount() + INPUT_TARGET_CLASS_INSTRUCTION);
+    }
+
+    private void setTargetClassInstruction(Value n) {
+        inputs().set(super.inputCount() + INPUT_TARGET_CLASS_INSTRUCTION, n);
+    }
+
+
+    /**
+     * Gets the target class, i.e. the class being cast to, or the class being tested against.
+     * @return the target class
+     */
+    public RiType targetClass() {
+        return targetClassInstruction() instanceof Constant ? (RiType) targetClassInstruction().asConstant().asObject() : null;
+    }
+
+    /**
+     * Creates a new TypeCheck instruction.
+     * @param targetClass the class which is being casted to or checked against
+     * @param object the instruction which produces the object
+     * @param kind the result type of this instruction
+     * @param inputCount
+     * @param successorCount
+     * @param graph
+     */
+    public TypeCheck(Value targetClassInstruction, Value object, CiKind kind, int inputCount, int successorCount, Graph graph) {
+        super(kind, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+        setObject(object);
+        setTargetClassInstruction(targetClassInstruction);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/UnsignedRightShift.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,115 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+
+public final class UnsignedRightShift extends Shift {
+    private static final UnsignedRightShiftCanonicalizerOp CANONICALIZER = new UnsignedRightShiftCanonicalizerOp();
+
+    public UnsignedRightShift(CiKind kind, Value x, Value y, Graph graph) {
+        super(kind, kind == CiKind.Int ? Bytecodes.IUSHR : Bytecodes.LUSHR, x, y, graph);
+    }
+
+    @Override
+    public String shortName() {
+        return ">>>";
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        UnsignedRightShift x = new UnsignedRightShift(kind, null, null, into);
+        return x;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static class UnsignedRightShiftCanonicalizerOp implements CanonicalizerOp {
+        @Override
+        public Node canonical(Node node) {
+            UnsignedRightShift ushr = (UnsignedRightShift) node;
+            CiKind kind = ushr.kind;
+            Graph graph = ushr.graph();
+            Value value = ushr.x();
+            Value y = ushr.y();
+            if (y.isConstant()) {
+                int amount = y.asConstant().asInt();
+                int originalAmout = amount;
+                int mask;
+                if (kind == CiKind.Int) {
+                    mask = 0x1f;
+                } else {
+                    assert kind == CiKind.Long;
+                    mask = 0x3f;
+                }
+                amount &= mask;
+                if (value.isConstant()) {
+                    if (kind == CiKind.Int) {
+                        return Constant.forInt(value.asConstant().asInt() >>> amount, graph);
+                    } else {
+                        assert kind == CiKind.Long;
+                        return Constant.forLong(value.asConstant().asLong() >>> amount, graph);
+                    }
+                }
+                if (amount == 0) {
+                    return value;
+                }
+                if (value instanceof Shift) {
+                    Shift other = (Shift) value;
+                    if (other.y().isConstant()) {
+                        int otherAmount = other.y().asConstant().asInt() & mask;
+                        if (other instanceof UnsignedRightShift) {
+                            int total = amount + otherAmount;
+                            if (total != (total & mask)) {
+                                return Constant.forInt(0, graph);
+                            }
+                            return new UnsignedRightShift(kind, other.x(), Constant.forInt(total, graph), graph);
+                        } else if (other instanceof LeftShift && otherAmount == amount) {
+                            if (kind == CiKind.Long) {
+                                return new And(kind, other.x(), Constant.forLong(-1L >>> amount, graph), graph);
+                            } else {
+                                assert kind == CiKind.Int;
+                                return new And(kind, other.x(), Constant.forInt(-1 >>> amount, graph), graph);
+                            }
+                        }
+                    }
+                }
+                if (originalAmout != amount) {
+                    return new UnsignedRightShift(kind, value, Constant.forInt(amount, graph), graph);
+                }
+            }
+            return ushr;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Unwind.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+/**
+ * Unwind takes an exception object, destroys the current stack frame and passes the exception object to the system's exception dispatch code.
+ */
+public final class Unwind extends FixedNode {
+
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_EXCEPTION = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The instruction that produces the exception object.
+     */
+     public Value exception() {
+        return (Value) inputs().get(super.inputCount() + INPUT_EXCEPTION);
+    }
+
+    public Value setException(Value n) {
+        assert n == null || n.kind == CiKind.Object;
+        return (Value) inputs().set(super.inputCount() + INPUT_EXCEPTION, n);
+    }
+
+    public Unwind(Value exception, Graph graph) {
+        super(CiKind.Object, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        setException(exception);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitUnwind(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(kind.typeChar).print("unwind ").print(exception());
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        Unwind x = new Unwind(null, into);
+        super.copyInto(x);
+        return x;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Value.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * This class represents a value within the HIR graph, including local variables, phis, and
+ * all other instructions.
+ */
+public abstract class Value extends Node {
+
+    /**
+     * The kind of this value. This is {@link CiKind#Void} for instructions that produce no value.
+     * This kind is guaranteed to be a {@linkplain CiKind#stackKind() stack kind}.
+     */
+    public final CiKind kind;
+
+    protected CiValue operand = CiValue.IllegalValue;
+
+    /**
+     * Creates a new value with the specified kind.
+     * @param kind the type of this value
+     * @param inputCount
+     * @param successorCount
+     * @param graph
+     */
+    public Value(CiKind kind, int inputCount, int successorCount, Graph graph) {
+        super(inputCount, successorCount, graph);
+        assert kind != null && kind == kind.stackKind() : kind + " != " + kind.stackKind();
+        this.kind = kind;
+    }
+
+    /**
+     * Checks whether this value is a constant (i.e. it is of type {@link Constant}.
+     * @return {@code true} if this value is a constant
+     */
+    public final boolean isConstant() {
+        return this instanceof Constant;
+    }
+
+    /**
+     * Checks whether this value represents the null constant.
+     * @return {@code true} if this value represents the null constant
+     */
+    public final boolean isNullConstant() {
+        return this instanceof Constant && ((Constant) this).value.isNull();
+    }
+
+    /**
+     * Convert this value to a constant if it is a constant, otherwise return null.
+     * @return the {@link CiConstant} represented by this value if it is a constant; {@code null}
+     * otherwise
+     */
+    public final CiConstant asConstant() {
+        if (this instanceof Constant) {
+            return ((Constant) this).value;
+        }
+        return null;
+    }
+
+    /**
+     * Gets the LIR operand associated with this instruction.
+     * @return the LIR operand for this instruction
+     */
+    public final CiValue operand() {
+        return operand;
+    }
+
+    /**
+     * Sets the LIR operand associated with this instruction.
+     * @param operand the operand to associate with this instruction
+     */
+    public final void setOperand(CiValue operand) {
+        assert this.operand.isIllegal() : "operand cannot be set twice";
+        assert operand != null && operand.isLegal() : "operand must be legal";
+        assert operand.kind.stackKind() == this.kind;
+        assert !(this instanceof VirtualObject);
+        this.operand = operand;
+    }
+
+    /**
+     * Clears the LIR operand associated with this instruction.
+     */
+    public final void clearOperand() {
+        this.operand = CiValue.IllegalValue;
+    }
+
+    /**
+     * Computes the exact type of the result of this instruction, if possible.
+     * @return the exact type of the result of this instruction, if it is known; {@code null} otherwise
+     */
+    public RiType exactType() {
+        return null; // default: unknown exact type
+    }
+
+    /**
+     * Computes the declared type of the result of this instruction, if possible.
+     * @return the declared type of the result of this instruction, if it is known; {@code null} otherwise
+     */
+    public RiType declaredType() {
+        return null; // default: unknown declared type
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("#");
+        builder.append(id());
+        builder.append(' ');
+        if (id() < 10) {
+            builder.append(' ');
+        }
+        builder.append(getClass().getSimpleName());
+        builder.append(" [").append(flagsToString()).append("]");
+        return builder.toString();
+    }
+
+    public String flagsToString() {
+        StringBuilder sb = new StringBuilder();
+        return sb.toString();
+    }
+
+    /**
+     * This method supports the visitor pattern by accepting a visitor and calling the
+     * appropriate {@code visit()} method.
+     *
+     * @param v the visitor to accept
+     */
+    public void accept(ValueVisitor v) {
+        throw new IllegalStateException("No visit method for this node (" + this.getClass().getSimpleName() + ")");
+    }
+
+    public void print(LogStream out) {
+        out.print(this.getClass().toString());
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return (T) LIRGenerator.DELEGATE_TO_VALUE_VISITOR;
+        }
+        return super.lookup(clazz);
+    }
+
+
+    @Override
+    public Map<Object, Object> getDebugProperties() {
+        Map<Object, Object> properties = super.getDebugProperties();
+        properties.put("kind", kind.toString());
+        properties.put("operand", operand == null ? "null" : operand.toString());
+        return properties;
+    }
+
+    /*@Override
+    public Iterable<? extends Node> dataUsages() {
+        final Iterator<? extends Node> dataUsages = super.dataUsages().iterator();
+        return new Iterable<Node>() {
+            @Override
+            public Iterator<Node> iterator() {
+                return new StateSplit.FilteringIterator(dataUsages, FrameState.class);
+            }
+        };
+    }*/
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ValueAnchor.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The ValueAnchor instruction keeps non-CFG nodes above a certain point in the graph.
+ */
+public final class ValueAnchor extends FixedNodeWithNext {
+
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_OBJECT = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The instruction that should be scheduled before this anchor.
+     */
+     public Value object() {
+        return (Value) inputs().get(super.inputCount() + INPUT_OBJECT);
+    }
+
+    public Value setObject(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_OBJECT, n);
+    }
+
+    /**
+     * Constructs a new Anchor instruction.
+     * @param succ the successor block of the anchor
+     * @param graph
+     */
+    public ValueAnchor(Value object, Graph graph) {
+        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        setObject(object);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitValueAnchor(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("value_anchor ").print(object());
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        ValueAnchor x = new ValueAnchor(null, into);
+        super.copyInto(x);
+        return x;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ValueClosure.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+/**
+ * The {@code ValueClosure} interface represents a first-class
+ * function that can be applied to a value.
+ */
+public interface ValueClosure {
+    Value apply(Value i);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ValueVisitor.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.value.*;
+
+/**
+ * The {@link ValueVisitor} implements one half of the visitor
+ * pattern for {@linkplain Value IR values}, allowing clients to implement functionality
+ * depending on the type of an value without doing type tests.
+ */
+public abstract class ValueVisitor {
+    // Checkstyle: stop
+    public abstract void visitArithmetic(Arithmetic i);
+    public abstract void visitArrayLength(ArrayLength i);
+    public abstract void visitMerge(Merge i);
+    public abstract void visitCheckCast(CheckCast i);
+    public abstract void visitMaterialize(NormalizeCompare i);
+    public abstract void visitConstant(Constant i);
+    public abstract void visitConvert(Convert i);
+    public abstract void visitExceptionObject(ExceptionObject i);
+    public abstract void visitEndNode(EndNode i);
+    public abstract void visitFrameState(FrameState i);
+    public abstract void visitAnchor(Anchor i);
+    public abstract void visitIf(If i);
+    public abstract void visitIfOp(Conditional i);
+    public abstract void visitInvoke(Invoke i);
+    public abstract void visitLoadField(LoadField i);
+    public abstract void visitLoadIndexed(LoadIndexed i);
+    public abstract void visitLocal(Local i);
+    public abstract void visitLogic(Logic i);
+    public abstract void visitLookupSwitch(LookupSwitch i);
+    public abstract void visitMemoryRead(ReadNode i);
+    public abstract void visitMemoryWrite(WriteNode i);
+    public abstract void visitMonitorAddress(MonitorAddress monitorAddress);
+    public abstract void visitMonitorEnter(MonitorEnter i);
+    public abstract void visitMonitorExit(MonitorExit i);
+    public abstract void visitNegate(Negate i);
+    public abstract void visitNewInstance(NewInstance i);
+    public abstract void visitNewMultiArray(NewMultiArray i);
+    public abstract void visitNewObjectArray(NewObjectArray i);
+    public abstract void visitNewTypeArray(NewTypeArray i);
+    public abstract void visitFixedGuard(FixedGuard fixedGuard);
+    public abstract void visitPhi(Phi i);
+    public abstract void visitRegisterFinalizer(RegisterFinalizer i);
+    public abstract void visitReturn(Return i);
+    public abstract void visitShift(Shift i);
+    public abstract void visitStoreField(StoreField i);
+    public abstract void visitStoreIndexed(StoreIndexed i);
+    public abstract void visitTableSwitch(TableSwitch i);
+    public abstract void visitDeoptimize(Deoptimize deoptimize);
+    public abstract void visitUnwind(Unwind unwind);
+    public abstract void visitLoopBegin(LoopBegin loopBegin);
+    public abstract void visitLoopEnd(LoopEnd loopEnd);
+    public abstract void visitValueAnchor(ValueAnchor valueAnchor);
+    public abstract void visitGuardNode(GuardNode guardNode);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/VirtualObject.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,94 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.phases.EscapeAnalysisPhase.EscapeField;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+
+public class VirtualObject extends FloatingNode {
+
+    private static final int INPUT_COUNT = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    private EscapeField[] fields;
+    private RiType type;
+
+    public VirtualObject(RiType type, EscapeField[] fields, Graph graph) {
+        super(CiKind.Int, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.type = type;
+        this.fields = fields;
+    }
+
+    public RiType type() {
+        return type;
+    }
+
+    public EscapeField[] fields() {
+        return fields;
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        // nothing to do...
+    }
+
+    @Override
+    public Map<Object, Object> getDebugProperties() {
+        Map<Object, Object> properties = super.getDebugProperties();
+        properties.put("type", type);
+        return properties;
+    }
+
+    @Override
+    public String shortName() {
+        return "VirtualObject " + type.name();
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("virtualobject ").print(type.name());
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        VirtualObject x = new VirtualObject(type, fields, into);
+        return x;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/VirtualObjectField.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,130 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public class VirtualObjectField extends FloatingNode {
+
+    private static final int INPUT_COUNT = 3;
+    private static final int INPUT_OBJECT = 0;
+    private static final int INPUT_LAST_STATE = 1;
+    private static final int INPUT_INPUT = 2;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The instruction that specifies the virtual object instance.
+     */
+     public VirtualObject object() {
+        return (VirtualObject) inputs().get(super.inputCount() + INPUT_OBJECT);
+    }
+
+    private VirtualObject setObject(VirtualObject n) {
+        return (VirtualObject) inputs().set(super.inputCount() + INPUT_OBJECT, n);
+    }
+
+    /**
+     * The instruction that specifies the old state of the virtual object.
+     */
+     public FloatingNode lastState() {
+        return (FloatingNode) inputs().get(super.inputCount() + INPUT_LAST_STATE);
+    }
+
+    private FloatingNode setLastState(FloatingNode n) {
+        return (FloatingNode) inputs().set(super.inputCount() + INPUT_LAST_STATE, n);
+    }
+
+    /**
+     * The instruction that contains the new state of the specified field.
+     */
+     public Value input() {
+        return (Value) inputs().get(super.inputCount() + INPUT_INPUT);
+    }
+
+    public Value setInput(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_INPUT, n);
+    }
+
+    private int index;
+
+    /**
+     * Constructs a new ArrayLength instruction.
+     * @param array the instruction producing the array
+     * @param newFrameState the state after executing this instruction
+     */
+    public VirtualObjectField(VirtualObject object, FloatingNode lastState, Value input, int index, Graph graph) {
+        super(CiKind.Int, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.index = index;
+        setObject(object);
+        setLastState(lastState);
+        setInput(input);
+    }
+
+    public int index() {
+        return index;
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        // nothing to do...
+    }
+
+    @Override
+    public Map<Object, Object> getDebugProperties() {
+        Map<Object, Object> properties = super.getDebugProperties();
+        properties.put("index", index);
+        return properties;
+    }
+
+    @Override
+    public String shortName() {
+        return "VirtualObjectField " + object().fields()[index].name();
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(object()).print(".").print(object().fields()[index].name()).print("=").print(input());
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        VirtualObjectField x = new VirtualObjectField(null, null, null, index, into);
+        return x;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/WriteMemoryCheckpointNode.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,57 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class WriteMemoryCheckpointNode extends AbstractMemoryCheckpointNode {
+
+    private static final int SUCCESSOR_COUNT = 0;
+    private static final int INPUT_COUNT = 0;
+
+    public WriteMemoryCheckpointNode(Graph graph) {
+        this(CiKind.Illegal, 0, 0, graph);
+    }
+
+    public WriteMemoryCheckpointNode(CiKind result, int inputCount, int successorCount, Graph graph) {
+        super(result, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+    }
+
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return null;
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        WriteMemoryCheckpointNode x = new WriteMemoryCheckpointNode(into);
+        super.copyInto(x);
+        return x;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/WriteNode.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class WriteNode extends AccessNode {
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_VALUE = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    public Value value() {
+        return (Value) inputs().get(super.inputCount() + INPUT_VALUE);
+    }
+
+    public void setValue(Value v) {
+        inputs().set(super.inputCount() + INPUT_VALUE, v);
+    }
+
+    public WriteNode(CiKind kind, Value object, Value value, LocationNode location, Graph graph) {
+        super(kind, object, location, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        setValue(value);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitMemoryWrite(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("mem write to ").print(object()).print(" with value").print(value());
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        WriteNode x = new WriteNode(super.kind, null, null, null, into);
+        super.copyInto(x);
+        return x;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/WriteVectorNode.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,84 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class WriteVectorNode extends AccessVectorNode {
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_VALUES = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    public void setValues(AbstractVectorNode length) {
+        inputs().set(super.inputCount() + INPUT_VALUES, length);
+    }
+
+    public AbstractVectorNode values() {
+        return (AbstractVectorNode) inputs().get(super.inputCount() + INPUT_VALUES);
+    }
+
+    public WriteVectorNode(AbstractVectorNode vector, Value object, LocationNode location, AbstractVectorNode values, Graph graph) {
+        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, vector, object, location, graph);
+        setValues(values);
+    }
+
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return null;
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("write vector node " + values());
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        WriteVectorNode x = new WriteVectorNode(null, null, null, null, into);
+        super.copyInto(x);
+        return x;
+    }
+
+
+    @Override
+    public void addToLoop(LoopBegin loop, IdentityHashMap<AbstractVectorNode, Value> nodes) {
+        LocationNode newLocation = LocationNode.create(LocationNode.getArrayLocation(location().getValueKind()), location().getValueKind(), location().displacement(), graph());
+        Value index = nodes.get(vector());
+        Value value = nodes.get(values());
+        assert index != null;
+        assert value != null;
+        newLocation.setIndex(index);
+        WriteNode writeNode = new WriteNode(location().getValueKind().stackKind(), object(), value, newLocation, graph());
+        loop.loopEnd().replaceAtPredecessors(writeNode);
+        writeNode.setNext(loop.loopEnd());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Xor.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,111 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+public final class Xor extends Logic {
+    private static final XorCanonicalizerOp CANONICALIZER = new XorCanonicalizerOp();
+
+    /**
+     * @param opcode
+     * @param kind
+     * @param x
+     * @param y
+     * @param graph
+     */
+    public Xor(CiKind kind, Value x, Value y, Graph graph) {
+        super(kind, kind == CiKind.Int ? Bytecodes.IXOR : Bytecodes.LXOR, x, y, graph);
+    }
+
+    @Override
+    public String shortName() {
+        return "^";
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        Xor x = new Xor(kind, null, null, into);
+        return x;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static class XorCanonicalizerOp implements CanonicalizerOp {
+        @Override
+        public Node canonical(Node node) {
+            assert node instanceof Xor;
+            Xor xor = (Xor) node;
+            CiKind kind = xor.kind;
+            Graph graph = xor.graph();
+            Value x = xor.x();
+            Value y = xor.y();
+            if (x == y) {
+                if (kind == CiKind.Int) {
+                    return Constant.forInt(0, graph);
+                } else {
+                    assert kind == CiKind.Long;
+                    return Constant.forLong(0L, graph);
+                }
+            }
+            if (x.isConstant() && !y.isConstant()) {
+                xor.swapOperands();
+                Value t = y;
+                y = x;
+                x = t;
+            }
+            if (x.isConstant()) {
+                if (kind == CiKind.Int) {
+                    return Constant.forInt(x.asConstant().asInt() ^ y.asConstant().asInt(), graph);
+                } else {
+                    assert kind == CiKind.Long;
+                    return Constant.forLong(x.asConstant().asLong() ^ y.asConstant().asLong(), graph);
+                }
+            } else if (y.isConstant()) {
+                if (kind == CiKind.Int) {
+                    int c = y.asConstant().asInt();
+                    if (c == 0) {
+                        return x;
+                    }
+                } else {
+                    assert kind == CiKind.Long;
+                    long c = y.asConstant().asLong();
+                    if (c == 0) {
+                        return x;
+                    }
+                }
+            }
+            return xor;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/package-info.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2010, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * High-level intermediate representation (HIR).
+ */
+package com.oracle.max.graal.compiler.ir;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/FrameMap.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,390 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.lir;
+
+import static com.sun.cri.ci.CiCallingConvention.Type.*;
+import static com.sun.cri.ci.CiKind.*;
+import static java.lang.reflect.Modifier.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.globalstub.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ci.CiCallingConvention.*;
+import com.sun.cri.ri.*;
+
+/**
+ * This class is used to build the stack frame layout for a compiled method.
+ *
+ * This is the format of a stack frame on an x86 (i.e. IA32 or X64) platform:
+ * <pre>
+ *   Base       Contents
+ *
+ *          :                                :
+ *          | incoming overflow argument n   |
+ *          |     ...                        |
+ *          | incoming overflow argument 0   |
+ *          | return address                 | Caller frame
+ *   -------+--------------------------------+----------------  ---
+ *          |                                |                   ^
+ *          : callee save area               :                   |
+ *          |                                |                   |
+ *          +--------------------------------+                   |
+ *          | alignment padding              |                   |
+ *          +--------------------------------+                   |
+ *          | ALLOCA block n                 |                   |
+ *          :     ...                        :                   |
+ *          | ALLOCA block 0                 | Current frame     |
+ *          +--------------------------------+                   |
+ *          | monitor n                      |                   |
+ *          :     ...                        :                   |
+ *          | monitor 0                      |                   |
+ *          +--------------------------------+    ---            |
+ *          | spill slot n                   |     ^           frame
+ *          :     ...                        :     |           size
+ *          | spill slot 0                   |  shared           |
+ *          +- - - - - - - - - - - - - - - - +   slot            |
+ *          | outgoing overflow argument n   |  indexes          |
+ *          |     ...                        |     |             |
+ *    %sp   | outgoing overflow argument 0   |     v             v
+ *   -------+--------------------------------+----------------  ---
+ *
+ * </pre>
+ * Note that the size {@link Bytecodes#ALLOCA ALLOCA} blocks and {@code monitor}s in the frame may be greater
+ * than the size of a {@linkplain CiTarget#spillSlotSize spill slot}.
+ */
+public final class FrameMap {
+
+    private final GraalCompilation compilation;
+    private final CiCallingConvention incomingArguments;
+
+    /**
+     * Number of monitors used in this frame.
+     */
+    private final int monitorCount;
+
+    /**
+     * The final frame size.
+     * Value is only set after register allocation is complete.
+     */
+    private int frameSize;
+
+    /**
+     * The number of spill slots allocated by the register allocator.
+     * The value {@code -2} means that the size of outgoing argument stack slots
+     * is not yet fixed. The value {@code -1} means that the register
+     * allocator has started allocating spill slots and so the size of
+     * outgoing stack slots cannot change as outgoing stack slots and
+     * spill slots share the same slot index address space.
+     */
+    private int spillSlotCount;
+
+    /**
+     * The amount of memory allocated within the frame for uses of {@link Bytecodes#ALLOCA}.
+     */
+    private int stackBlocksSize;
+
+    /**
+     * Area occupied by outgoing overflow arguments.
+     * This value is adjusted as calling conventions for outgoing calls are retrieved.
+     */
+    private int outgoingSize;
+
+    /**
+     * Creates a new frame map for the specified method.
+     *
+     * @param compilation the compilation context
+     * @param method the outermost method being compiled
+     * @param monitors the number of monitors allocated on the stack for this method
+     */
+    public FrameMap(GraalCompilation compilation, RiMethod method, int monitors) {
+        this.compilation = compilation;
+        this.frameSize = -1;
+        this.spillSlotCount = -2;
+
+        assert monitors >= 0 : "not set";
+        monitorCount = monitors;
+        if (method == null) {
+            incomingArguments = new CiCallingConvention(new CiValue[0], 0);
+        } else {
+            CiKind receiver = !isStatic(method.accessFlags()) ? method.holder().kind() : null;
+            incomingArguments = getCallingConvention(CiUtil.signatureToKinds(method.signature(), receiver), JavaCallee);
+        }
+    }
+
+    /**
+     * Gets the calling convention for a call with the specified signature.
+     *
+     * @param type the type of calling convention being requested
+     * @param signature the signature of the arguments
+     * @return a {@link CiCallingConvention} instance describing the location of parameters and the return value
+     */
+    public CiCallingConvention getCallingConvention(CiKind[] signature, Type type) {
+        CiCallingConvention cc = compilation.registerConfig.getCallingConvention(type, signature, compilation.target, false);
+        if (type == RuntimeCall) {
+            assert cc.stackSize == 0 : "runtime call should not have stack arguments";
+        } else if (type.out) {
+            assert frameSize == -1 : "frame size must not yet be fixed!";
+            reserveOutgoing(cc.stackSize);
+        }
+        return cc;
+    }
+
+    /**
+     * Gets the calling convention for the incoming arguments to the compiled method.
+     * @return the calling convention for incoming arguments
+     */
+    public CiCallingConvention incomingArguments() {
+        return incomingArguments;
+    }
+
+    /**
+     * Gets the frame size of the compiled frame.
+     * @return the size in bytes of the frame
+     */
+    public int frameSize() {
+        assert this.frameSize != -1 : "frame size not computed yet";
+        return frameSize;
+    }
+
+    /**
+     * Sets the frame size for this frame.
+     * @param frameSize the frame size in bytes
+     */
+    public void setFrameSize(int frameSize) {
+        assert this.frameSize == -1 : "should only be calculated once";
+        this.frameSize = frameSize;
+    }
+
+    /**
+     * Computes the frame size for this frame, given the number of spill slots.
+     * @param spillSlotCount the number of spill slots
+     */
+    public void finalizeFrame(int spillSlotCount) {
+        assert this.spillSlotCount == -1 : "can only be set once";
+        assert this.frameSize == -1 : "should only be calculated once";
+        assert spillSlotCount >= 0 : "must be positive";
+
+        this.spillSlotCount = spillSlotCount;
+        int frameSize = offsetToStackBlocksEnd();
+        frameSize += compilation.registerConfig.getCalleeSaveLayout().size;
+        this.frameSize = compilation.target.alignFrameSize(frameSize);
+    }
+
+    /**
+     * Informs the frame map that the compiled code uses a particular global stub, which
+     * may need stack space for outgoing arguments.
+     *
+     * @param stub the global stub
+     */
+    public void usesGlobalStub(GlobalStub stub) {
+        reserveOutgoing(stub.argsSize);
+    }
+
+    /**
+     * Converts a stack slot into a stack address.
+     *
+     * @param slot a stack slot
+     * @return a stack address
+     */
+    public CiAddress toStackAddress(CiStackSlot slot) {
+        int size = compilation.target.sizeInBytes(slot.kind);
+        if (slot.inCallerFrame()) {
+            int offset = slot.index() * compilation.target.spillSlotSize + frameSize() + 8;
+            return new CiAddress(slot.kind, CiRegister.Frame.asValue(), offset);
+        } else {
+            int offset = offsetForOutgoingOrSpillSlot(slot.index(), size);
+            return new CiAddress(slot.kind, CiRegister.Frame.asValue(), offset);
+        }
+    }
+
+    /**
+     * Gets the stack address within this frame for a given reserved stack block.
+     *
+     * @param stackBlock the value returned from {@link #reserveStackBlock(int)} identifying the stack block
+     * @return a representation of the stack location
+     */
+    public CiAddress toStackAddress(StackBlock stackBlock) {
+        return new CiAddress(CiKind.Word, compilation.registerConfig.getFrameRegister().asValue(Word), offsetForStackBlock(stackBlock));
+    }
+
+    /**
+     * Converts the monitor index into the stack address of the object reference in the on-stack monitor.
+     *
+     * @param monitorIndex the monitor index
+     * @return a representation of the stack address
+     */
+    public CiStackSlot toMonitorObjectStackAddress(int monitorIndex) {
+        int byteIndex = offsetForMonitorObject(monitorIndex);
+        assert byteIndex % compilation.target.wordSize == 0;
+        return CiStackSlot.get(CiKind.Object, byteIndex / compilation.target.wordSize);
+    }
+
+    /**
+     * Converts the monitor index into the stack address of the on-stak monitor.
+     *
+     * @param monitorIndex the monitor index
+     * @return a representation of the stack address
+     */
+    public CiStackSlot toMonitorBaseStackAddress(int monitorIndex) {
+        int byteIndex = offsetForMonitorBase(monitorIndex);
+        assert byteIndex % compilation.target.wordSize == 0;
+        return CiStackSlot.get(CiKind.Object, byteIndex / compilation.target.wordSize);
+    }
+
+    /**
+     * Reserves space for stack-based outgoing arguments.
+     *
+     * @param argsSize the amount of space to reserve for stack-based outgoing arguments
+     */
+    public void reserveOutgoing(int argsSize) {
+        assert spillSlotCount == -2 : "cannot reserve outgoing stack slot space once register allocation has started";
+        if (argsSize > outgoingSize) {
+            outgoingSize = Util.roundUp(argsSize, compilation.target.spillSlotSize);
+        }
+    }
+
+    /**
+     * Encapsulates the details of a stack block reserved by a call to {@link FrameMap#reserveStackBlock(int)}.
+     */
+    public static final class StackBlock {
+        /**
+         * The size of this stack block.
+         */
+        public final int size;
+
+        /**
+         * The offset of this stack block within the frame space reserved for stack blocks.
+         */
+        public final int offset;
+
+        public StackBlock(int size, int offset) {
+            this.size = size;
+            this.offset = offset;
+        }
+    }
+
+    /**
+     * Reserves a block of memory in the frame of the method being compiled.
+     *
+     * @param size the number of bytes to reserve
+     * @return a descriptor of the reserved block that can be used with {@link #toStackAddress(StackBlock)} once register
+     *         allocation is complete and the size of the frame has been {@linkplain #finalizeFrame(int) finalized}.
+     */
+    public StackBlock reserveStackBlock(int size) {
+        int wordSize = compilation.target.sizeInBytes(CiKind.Word);
+        assert (size % wordSize) == 0;
+        StackBlock block = new StackBlock(size, stackBlocksSize);
+        stackBlocksSize += size;
+        return block;
+    }
+
+    private int offsetForStackBlock(StackBlock stackBlock) {
+        assert stackBlock.offset >= 0 && stackBlock.offset + stackBlock.size <= stackBlocksSize : "invalid stack block";
+        int offset = offsetToStackBlocks() + stackBlock.offset;
+        assert offset <= (frameSize() - stackBlock.size) : "spill outside of frame";
+        return offset;
+    }
+
+    /**
+     * Gets the stack pointer offset for a outgoing stack argument or compiler spill slot.
+     *
+     * @param slotIndex the index of the stack slot within the slot index space reserved for
+     * @param size
+     * @return
+     */
+    private int offsetForOutgoingOrSpillSlot(int slotIndex, int size) {
+        assert slotIndex >= 0 && slotIndex < (initialSpillSlot() + spillSlotCount) : "invalid spill slot";
+        int offset = slotIndex * compilation.target.spillSlotSize;
+        assert offset <= (frameSize() - size) : "slot outside of frame";
+        return offset;
+    }
+
+    private int offsetForMonitorBase(int index) {
+        assert index >= 0 && index < monitorCount : "invalid monitor index : " + index + " (monitorCount=" + monitorCount + ")";
+        int size = compilation.runtime.sizeOfBasicObjectLock();
+        assert size != 0 : "monitors are not on the stack in this VM";
+        int offset = offsetToMonitors() + index * size;
+        assert offset <= (frameSize() - size) : "monitor outside of frame";
+        return offset;
+    }
+
+    private int offsetToSpillArea() {
+        return outgoingSize;
+    }
+
+    private int offsetToSpillEnd() {
+        return offsetToSpillArea() + spillSlotCount * compilation.target.spillSlotSize;
+    }
+
+    private int offsetToMonitors() {
+        return offsetToCustomArea() + customAreaSize();
+    }
+
+    public int customAreaSize() {
+        return compilation.runtime.getCustomStackAreaSize();
+    }
+
+    public int offsetToCustomArea() {
+        return offsetToSpillEnd();
+    }
+
+    private int offsetToMonitorsEnd() {
+        return offsetToMonitors() + (monitorCount * compilation.runtime.sizeOfBasicObjectLock());
+    }
+
+    private int offsetToStackBlocks() {
+        return offsetToMonitorsEnd();
+    }
+
+    private int offsetToStackBlocksEnd() {
+        return offsetToStackBlocks() + stackBlocksSize;
+    }
+
+    public int offsetToCalleeSaveAreaStart() {
+        return offsetToCalleeSaveAreaEnd() - compilation.registerConfig.getCalleeSaveLayout().size;
+    }
+
+    public int offsetToCalleeSaveAreaEnd() {
+        return frameSize;
+    }
+
+    private int offsetForMonitorObject(int index)  {
+        return offsetForMonitorBase(index) + compilation.runtime.basicObjectLockOffsetInBytes();
+    }
+
+    /**
+     * Gets the index of the first available spill slot relative to the base of the frame.
+     * After this call, no further outgoing stack slots can be {@linkplain #reserveOutgoing(int) reserved}.
+     *
+     * @return the index of the first available spill slot
+     */
+    public int initialSpillSlot() {
+        if (spillSlotCount == -2) {
+            spillSlotCount = -1;
+        }
+        return outgoingSize / compilation.target.spillSlotSize;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRAssembler.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,473 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.lir;
+
+import java.util.*;
+
+import com.oracle.max.asm.*;
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.asm.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.lir.FrameMap.StackBlock;
+import com.oracle.max.graal.compiler.util.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ci.CiTargetMethod.Mark;
+import com.sun.cri.ri.*;
+import com.sun.cri.xir.CiXirAssembler.XirMark;
+
+/**
+ * The {@code LIRAssembler} class definition.
+ */
+public abstract class LIRAssembler {
+
+    public final GraalCompilation compilation;
+    public final TargetMethodAssembler tasm;
+    public final AbstractAssembler asm;
+    public final FrameMap frameMap;
+    public int registerRestoreEpilogueOffset = -1;
+
+    protected final List<SlowPath> xirSlowPath;
+
+    private int lastDecodeStart;
+
+    protected static class SlowPath {
+        public final LIRXirInstruction instruction;
+        public final Label[] labels;
+        public final Map<XirMark, Mark> marks;
+
+        public SlowPath(LIRXirInstruction instruction, Label[] labels, Map<XirMark, Mark> marks) {
+            this.instruction = instruction;
+            this.labels = labels;
+            this.marks = marks;
+        }
+    }
+
+    public LIRAssembler(GraalCompilation compilation) {
+        this.compilation = compilation;
+        this.tasm = compilation.assembler();
+        this.asm = tasm.asm;
+        this.frameMap = compilation.frameMap();
+        this.xirSlowPath = new ArrayList<SlowPath>();
+    }
+
+    protected RiMethod method() {
+        return compilation.method;
+    }
+
+    protected void addSlowPath(SlowPath sp) {
+        xirSlowPath.add(sp);
+    }
+
+    public void emitLocalStubs() {
+        for (SlowPath sp : xirSlowPath) {
+            emitSlowPath(sp);
+        }
+
+        // No more code may be emitted after this point
+    }
+
+    protected int codePos() {
+        return asm.codeBuffer.position();
+    }
+
+    public abstract void emitTraps();
+
+    public void emitCode(List<LIRBlock> hir) {
+        if (GraalOptions.PrintLIR && !TTY.isSuppressed()) {
+            LIRList.printLIR(hir);
+        }
+
+        for (LIRBlock b : hir) {
+            emitBlock(b);
+        }
+
+        assert checkNoUnboundLabels();
+    }
+
+    void emitBlock(LIRBlock block) {
+
+        if (block.align()) {
+            emitAlignment();
+        }
+
+        block.setBlockEntryPco(codePos());
+
+        if (GraalOptions.PrintLIRWithAssembly) {
+            block.printWithoutPhis(TTY.out());
+        }
+
+        assert block.lir() != null : "must have LIR";
+        if (GraalOptions.CommentedAssembly) {
+            String st = String.format(" block B%d", block.blockID());
+            tasm.blockComment(st);
+        }
+
+        emitLirList(block.lir());
+    }
+
+    void emitLirList(LIRList list) {
+        doPeephole(list);
+
+        for (LIRInstruction op : list.instructionsList()) {
+            if (GraalOptions.CommentedAssembly) {
+                // Only print out branches
+                if (op.code == LIROpcode.Branch) {
+                    tasm.blockComment(op.toStringWithIdPrefix());
+                }
+            }
+            if (GraalOptions.PrintLIRWithAssembly && !TTY.isSuppressed()) {
+                // print out the LIR operation followed by the resulting assembly
+                TTY.println(op.toStringWithIdPrefix());
+                TTY.println();
+            }
+
+            op.emitCode(this);
+
+            if (GraalOptions.PrintLIRWithAssembly) {
+                printAssembly(asm);
+            }
+        }
+    }
+
+    private void printAssembly(AbstractAssembler asm) {
+        byte[] currentBytes = asm.codeBuffer.copyData(lastDecodeStart, asm.codeBuffer.position());
+        if (currentBytes.length > 0) {
+            String disasm = compilation.runtime.disassemble(currentBytes, lastDecodeStart);
+            if (disasm.length() != 0) {
+                TTY.println(disasm);
+            } else {
+                TTY.println("Code [+%d]: %d bytes", lastDecodeStart, currentBytes.length);
+                Util.printBytes(lastDecodeStart, currentBytes, GraalOptions.PrintAssemblyBytesPerLine);
+            }
+        }
+        lastDecodeStart = asm.codeBuffer.position();
+    }
+
+    boolean checkNoUnboundLabels() {
+//        for (int i = 0; i < branchTargetBlocks.size() - 1; i++) {
+//            if (!branchTargetBlocks.get(i).label().isBound()) {
+//                TTY.println(String.format("label of block B%d is not bound", branchTargetBlocks.get(i).blockID()));
+//                assert false : "unbound label";
+//            }
+//        }
+
+        return true;
+    }
+
+    void emitCall(LIRCall op) {
+        verifyOopMap(op.info);
+
+        switch (op.code) {
+            case DirectCall:
+                emitCallAlignment(op.code);
+                // fall through
+            case ConstDirectCall:
+                if (op.marks != null) {
+                    op.marks.put(XirMark.CALLSITE, tasm.recordMark(null, new Mark[0]));
+                }
+                emitDirectCall(op.target, op.info);
+                break;
+            case IndirectCall:
+                emitCallAlignment(op.code);
+                if (op.marks != null) {
+                    op.marks.put(XirMark.CALLSITE, tasm.recordMark(null, new Mark[0]));
+                }
+                emitIndirectCall(op.target, op.info, op.targetAddress());
+                break;
+            case NativeCall: {
+                emitNativeCall((String) op.target, op.info, op.targetAddress());
+                break;
+            }
+            case TemplateCall: {
+                emitTemplateCall(op.targetAddress());
+                break;
+            }
+            default:
+                throw Util.shouldNotReachHere();
+        }
+    }
+
+    void emitOpLabel(LIRLabel op) {
+        asm.bind(op.label());
+    }
+
+    void emitOp1(LIROp1 op) {
+        switch (op.code) {
+            case Move:
+                assert !op.operand().isIllegal();
+                if (op.moveKind() == LIROp1.LIRMoveKind.Volatile) {
+                    emitVolatileMove(op.operand(), op.result(), op.kind, op.info);
+                } else {
+                    moveOp(op.operand(), op.result(), op.kind, op.info, op.moveKind() == LIROp1.LIRMoveKind.Unaligned);
+                }
+                break;
+            case Prefetchr:
+                emitReadPrefetch(op.operand());
+                break;
+            case Prefetchw:
+                emitReadPrefetch(op.operand());
+                break;
+            case Return:
+                emitReturn(op.operand());
+                break;
+            case Neg:
+                emitNegate((LIRNegate) op);
+                break;
+            case Lea:
+                emitLea(op.operand(), op.result());
+                break;
+            case NullCheck:
+                emitNullCheck(op.operand(), op.info);
+                break;
+            case Lsb:
+                emitSignificantBitOp(false,  op.operand(), op.result());
+                break;
+            case Msb:
+                emitSignificantBitOp(true,  op.operand(), op.result());
+                break;
+            default:
+                throw Util.shouldNotReachHere();
+        }
+    }
+
+    public void emitOp0(LIROp0 op) {
+        switch (op.code) {
+            case Label:
+                throw Util.shouldNotReachHere();
+            case Breakpoint:
+                emitBreakpoint();
+                break;
+            default:
+                throw Util.shouldNotReachHere();
+        }
+    }
+
+    protected void emitOp2(LIROp2 op) {
+        switch (op.code) {
+            case Cmp:
+                emitCompare(op.condition(), op.operand1(), op.operand2(), op);
+                break;
+
+            case Cmpl2i:
+            case Cmpfd2i:
+            case Ucmpfd2i:
+                emitCompare2Int(op.code, op.operand1(), op.operand2(), op.result(), op);
+                break;
+
+            case Cmove:
+                emitConditionalMove(op.condition(), op.operand1(), op.operand2(), op.result());
+                break;
+
+            case Shl:
+            case Shr:
+            case Ushr:
+                if (op.operand2().isConstant()) {
+                    emitShiftOp(op.code, op.operand1(), ((CiConstant) op.operand2()).asInt(), op.result());
+                } else {
+                    emitShiftOp(op.code, op.operand1(), op.operand2(), op.result(), op.tmp());
+                }
+                break;
+
+            case Add:
+            case Sub:
+            case Mul:
+            case Div:
+            case Rem:
+                emitArithOp(op.code, op.operand1(), op.operand2(), op.result(), op.info);
+                break;
+
+            case Abs:
+            case Sqrt:
+            case Sin:
+            case Tan:
+            case Cos:
+            case Log:
+            case Log10:
+                emitIntrinsicOp(op.code, op.operand1(), op.operand2(), op.result(), op);
+                break;
+
+            case LogicAnd:
+            case LogicOr:
+            case LogicXor:
+                emitLogicOp(op.code, op.operand1(), op.operand2(), op.result());
+                break;
+
+            default:
+                throw Util.shouldNotReachHere();
+        }
+    }
+
+    public void moveOp(CiValue src, CiValue dest, CiKind kind, LIRDebugInfo info, boolean unaligned) {
+        if (src.isRegister()) {
+            if (dest.isRegister()) {
+                assert info == null : "no patching and info allowed here";
+                reg2reg(src, dest);
+            } else if (dest.isStackSlot()) {
+                assert info == null : "no patching and info allowed here";
+                reg2stack(src, dest, kind);
+            } else if (dest.isAddress()) {
+                reg2mem(src, dest, kind, info, unaligned);
+            } else {
+                throw Util.shouldNotReachHere();
+            }
+
+        } else if (src.isStackSlot()) {
+            assert info == null : "no patching and info allowed here";
+            if (dest.isRegister()) {
+                stack2reg(src, dest, kind);
+            } else if (dest.isStackSlot()) {
+                stack2stack(src, dest, kind);
+            } else {
+                throw Util.shouldNotReachHere();
+            }
+
+        } else if (src.isConstant()) {
+            if (dest.isRegister()) {
+                const2reg(src, dest, info); // patching is possible
+            } else if (dest.isStackSlot()) {
+                assert info == null : "no patching and info allowed here";
+                const2stack(src, dest);
+            } else if (dest.isAddress()) {
+                const2mem(src, dest, kind, info);
+            } else {
+                throw Util.shouldNotReachHere();
+            }
+
+        } else if (src.isAddress()) {
+            if (dest.isStackSlot()) {
+                assert info == null && !unaligned;
+                mem2stack(src, dest, kind);
+            } else if (dest.isAddress()) {
+                assert info == null && !unaligned;
+                mem2mem(src, dest, kind);
+            } else {
+                mem2reg(src, dest, kind, info, unaligned);
+            }
+
+        } else {
+            throw Util.shouldNotReachHere(src.toString() + ", dest=" + dest.toString() + ", " + kind);
+        }
+    }
+
+    public void verifyOopMap(LIRDebugInfo info) {
+        if (GraalOptions.VerifyPointerMaps) {
+            // TODO: verify oops
+            Util.shouldNotReachHere();
+        }
+    }
+
+    protected abstract int initialFrameSizeInBytes();
+
+    protected abstract void doPeephole(LIRList list);
+
+    protected abstract void emitSlowPath(SlowPath sp);
+
+    public abstract void emitDeoptizationStub(LIRGenerator.DeoptimizationStub stub);
+
+    protected abstract void emitAlignment();
+
+    protected abstract void emitBreakpoint();
+
+    protected abstract void emitLea(CiValue src, CiValue dst);
+
+    protected abstract void emitNullCheck(CiValue src, LIRDebugInfo info);
+
+    protected abstract void emitNegate(LIRNegate negate);
+
+    protected abstract void emitMonitorAddress(int monitor, CiValue dst);
+
+    protected abstract void emitStackAllocate(StackBlock src, CiValue dst);
+
+    protected abstract void emitReturn(CiValue inOpr);
+
+    protected abstract void emitReadPrefetch(CiValue inOpr);
+
+    protected abstract void emitVolatileMove(CiValue inOpr, CiValue result, CiKind kind, LIRDebugInfo info);
+
+    protected abstract void emitLogicOp(LIROpcode code, CiValue inOpr1, CiValue inOpr2, CiValue dst);
+
+    protected abstract void emitIntrinsicOp(LIROpcode code, CiValue inOpr1, CiValue inOpr2, CiValue dst, LIROp2 op);
+
+    protected abstract void emitArithOp(LIROpcode code, CiValue inOpr1, CiValue inOpr2, CiValue dst, LIRDebugInfo info);
+
+    protected abstract void emitShiftOp(LIROpcode code, CiValue inOpr1, CiValue inOpr2, CiValue dst, CiValue tmpOpr);
+
+    protected abstract void emitShiftOp(LIROpcode code, CiValue inOpr1, int asJint, CiValue dst);
+
+    protected abstract void emitSignificantBitOp(boolean most, CiValue inOpr1, CiValue dst);
+
+    protected abstract void emitConditionalMove(Condition condition, CiValue inOpr1, CiValue inOpr2, CiValue dst);
+
+    protected abstract void emitCompare2Int(LIROpcode code, CiValue inOpr1, CiValue inOpr2, CiValue dst, LIROp2 op);
+
+    protected abstract void emitCompare(Condition condition, CiValue inOpr1, CiValue inOpr2, LIROp2 op);
+
+    protected abstract void emitBranch(LIRBranch branch);
+
+    protected abstract void emitTableSwitch(LIRTableSwitch tableSwitch);
+
+    protected abstract void emitConvert(LIRConvert convert);
+
+    protected abstract void emitOp3(LIROp3 op3);
+
+    protected abstract void emitCompareAndSwap(LIRCompareAndSwap compareAndSwap);
+
+    protected abstract void emitXir(LIRXirInstruction xirInstruction);
+
+    protected abstract void emitIndirectCall(Object target, LIRDebugInfo info, CiValue callAddress);
+
+    protected abstract void emitDirectCall(Object target, LIRDebugInfo info);
+
+    protected abstract void emitNativeCall(String symbol, LIRDebugInfo info, CiValue callAddress);
+
+    protected abstract void emitTemplateCall(CiValue address);
+
+    protected abstract void emitCallAlignment(LIROpcode code);
+
+    protected abstract void emitMemoryBarriers(int barriers);
+
+    protected abstract void reg2stack(CiValue src, CiValue dest, CiKind kind);
+
+    protected abstract void reg2mem(CiValue src, CiValue dest, CiKind kind, LIRDebugInfo info, boolean unaligned);
+
+    protected abstract void mem2reg(CiValue src, CiValue dest, CiKind kind, LIRDebugInfo info, boolean unaligned);
+
+    protected abstract void const2mem(CiValue src, CiValue dest, CiKind kind, LIRDebugInfo info);
+
+    protected abstract void const2stack(CiValue src, CiValue dest);
+
+    protected abstract void const2reg(CiValue src, CiValue dest, LIRDebugInfo info);
+
+    protected abstract void mem2stack(CiValue src, CiValue dest, CiKind kind);
+
+    protected abstract void mem2mem(CiValue src, CiValue dest, CiKind kind);
+
+    protected abstract void stack2stack(CiValue src, CiValue dest, CiKind kind);
+
+    protected abstract void stack2reg(CiValue src, CiValue dest, CiKind kind);
+
+    protected abstract void reg2reg(CiValue src, CiValue dest);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRBlock.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,300 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.lir;
+
+import java.util.*;
+
+import com.oracle.max.asm.*;
+import com.oracle.max.graal.compiler.alloc.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.compiler.value.*;
+import com.oracle.max.graal.graph.*;
+
+/**
+ * The {@code LIRBlock} class definition.
+ */
+public final class LIRBlock {
+
+    public final Label label;
+    private LIRList lir;
+    private final int blockID;
+    private FrameState lastState;
+    private List<Node> instructions = new ArrayList<Node>(4);
+    private List<LIRBlock> predecessors = new ArrayList<LIRBlock>(4);
+    private List<LIRBlock> successors = new ArrayList<LIRBlock>(4);
+    private LIRDebugInfo debugInfo;
+    private boolean align;
+
+    /**
+     * Bit map specifying which {@linkplain OperandPool operands} are live upon entry to this block.
+     * These are values used in this block or any of its successors where such value are not defined
+     * in this block.
+     * The bit index of an operand is its {@linkplain OperandPool#operandNumber(com.sun.cri.ci.CiValue) operand number}.
+     */
+    public BitMap liveIn;
+
+    /**
+     * Bit map specifying which {@linkplain OperandPool operands} are live upon exit from this block.
+     * These are values used in a successor block that are either defined in this block or were live
+     * upon entry to this block.
+     * The bit index of an operand is its {@linkplain OperandPool#operandNumber(com.sun.cri.ci.CiValue) operand number}.
+     */
+    public BitMap liveOut;
+
+    /**
+     * Bit map specifying which {@linkplain OperandPool operands} are used (before being defined) in this block.
+     * That is, these are the values that are live upon entry to the block.
+     * The bit index of an operand is its {@linkplain OperandPool#operandNumber(com.sun.cri.ci.CiValue) operand number}.
+     */
+    public BitMap liveGen;
+
+    /**
+     * Bit map specifying which {@linkplain OperandPool operands} are defined/overwritten in this block.
+     * The bit index of an operand is its {@linkplain OperandPool#operandNumber(com.sun.cri.ci.CiValue) operand number}.
+     */
+    public BitMap liveKill;
+
+    private int firstLirInstructionID;
+    private int lastLirInstructionID;
+    public int blockEntryPco;
+
+    public LIRBlock(Label label, LIRDebugInfo debugInfo) {
+        this.label = label;
+        blockID = -1;
+        this.debugInfo = debugInfo;
+    }
+
+    public LIRDebugInfo debugInfo() {
+        return this.debugInfo;
+    }
+
+    public LIRBlock(int blockID) {
+        this.blockID = blockID;
+        label = new Label();
+        loopIndex = -1;
+        linearScanNumber = blockID;
+        instructions = new ArrayList<Node>(4);
+        predecessors = new ArrayList<LIRBlock>(4);
+        successors = new ArrayList<LIRBlock>(4);
+    }
+
+    public List<Node> getInstructions() {
+        return instructions;
+    }
+
+    public int firstLirInstructionId() {
+        return firstLirInstructionID;
+    }
+
+    public boolean align() {
+        return align;
+    }
+
+    public void setAlign(boolean b) {
+        align = b;
+    }
+
+    public void setFirstLirInstructionId(int firstLirInstructionId) {
+        this.firstLirInstructionID = firstLirInstructionId;
+    }
+
+    public int lastLirInstructionId() {
+        return lastLirInstructionID;
+    }
+
+    public void setLastLirInstructionId(int lastLirInstructionId) {
+        this.lastLirInstructionID = lastLirInstructionId;
+    }
+
+    public int loopDepth;
+
+    public LIRList lir() {
+        return lir;
+    }
+
+    public void setLir(LIRList lir) {
+        this.lir = lir;
+    }
+
+    public void setBlockEntryPco(int codePos) {
+        this.blockEntryPco = codePos;
+    }
+
+    public void printWithoutPhis(LogStream out) {
+        out.println("LIR Block " + blockID());
+    }
+
+    public int blockID() {
+        return blockID;
+    }
+
+    public int numberOfPreds() {
+        return predecessors.size();
+    }
+
+    public int numberOfSux() {
+        return successors.size();
+    }
+
+    public boolean isPredecessor(LIRBlock block) {
+        return predecessors.contains(block);
+    }
+
+    public LIRBlock predAt(int i) {
+        return predecessors.get(i);
+    }
+
+    public LIRBlock suxAt(int i) {
+        return successors.get(i);
+    }
+
+    public List<LIRBlock> blockSuccessors() {
+        return successors;
+    }
+
+    @Override
+    public String toString() {
+        return "B" + blockID();
+    }
+
+    public List<LIRBlock> blockPredecessors() {
+        return predecessors;
+    }
+
+    public int loopDepth() {
+        return loopDepth;
+    }
+
+    public int loopIndex() {
+        return loopIndex;
+    }
+
+    public void setLoopIndex(int v) {
+        loopIndex = v;
+    }
+
+    public void setLoopDepth(int v) {
+        this.loopDepth = v;
+    }
+
+    private int loopIndex;
+
+    public Label label() {
+        return label;
+    }
+
+    private int linearScanNumber = -1;
+    private boolean linearScanLoopEnd;
+    private boolean linearScanLoopHeader;
+
+    public void setLinearScanNumber(int v) {
+        linearScanNumber = v;
+    }
+
+    public int linearScanNumber() {
+        return linearScanNumber;
+    }
+
+    public void setLinearScanLoopEnd() {
+        linearScanLoopEnd = true;
+    }
+
+    public boolean isLinearScanLoopEnd() {
+        return linearScanLoopEnd;
+    }
+
+    public void setLinearScanLoopHeader() {
+        this.linearScanLoopHeader = true;
+    }
+
+    public boolean isLinearScanLoopHeader() {
+        return linearScanLoopHeader;
+    }
+
+    public void replaceWith(LIRBlock other) {
+        for (LIRBlock pred : predecessors) {
+            Util.replaceAllInList(this, other, pred.successors);
+        }
+        for (int i = 0; i < other.predecessors.size(); ++i) {
+            if (other.predecessors.get(i) == this) {
+                other.predecessors.remove(i);
+                other.predecessors.addAll(i, this.predecessors);
+            }
+        }
+        successors.clear();
+        predecessors.clear();
+    }
+
+    public void setInstructions(List<Node> list) {
+        instructions = list;
+    }
+
+    public void setLastState(FrameState fs) {
+        lastState = fs;
+    }
+
+    public FrameState lastState() {
+        return lastState;
+    }
+
+    private Node first;
+    private Node last;
+
+    public Node firstInstruction() {
+        return first;
+    }
+
+
+    public Node lastInstruction() {
+        return last;
+    }
+
+    public void setFirstInstruction(Node n) {
+        first = n;
+    }
+
+
+    public void setLastInstruction(Node n) {
+        last = n;
+    }
+
+    public boolean endsWithJump() {
+        List<LIRInstruction> instructionsList = lir.instructionsList();
+        if (instructionsList.size() == 0) {
+            return false;
+        }
+        LIRInstruction lirInstruction = instructionsList.get(instructionsList.size() - 1);
+        if (lirInstruction instanceof LIRXirInstruction) {
+            LIRXirInstruction lirXirInstruction = (LIRXirInstruction) lirInstruction;
+            return (lirXirInstruction.falseSuccessor() != null) && (lirXirInstruction.trueSuccessor() != null);
+        }
+        LIROpcode code = lirInstruction.code;
+        return code == LIROpcode.Branch || code == LIROpcode.TableSwitch;
+    }
+
+    public boolean isExceptionEntry() {
+        return firstInstruction() instanceof ExceptionObject;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRBranch.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.lir;
+
+import com.oracle.max.asm.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.sun.cri.ci.*;
+
+/**
+ * @author Marcelo Cintra
+ * @author Thomas Wuerthinger
+ *
+ */
+public class LIRBranch extends LIRInstruction {
+
+    private Condition cond;
+    private Label label;
+
+    /**
+     * The target block of this branch.
+     */
+    private LIRBlock block;
+
+    /**
+     * This is the unordered block for a float branch.
+     */
+    private LIRBlock unorderedBlock;
+
+
+    public LIRBranch(Condition cond, Label label) {
+        this(cond, label, null);
+    }
+
+    /**
+     * Creates a new LIRBranch instruction.
+     *
+     * @param cond the branch condition
+     * @param label target label
+     *
+     */
+    public LIRBranch(Condition cond, Label label, LIRDebugInfo info) {
+        super(LIROpcode.Branch, CiValue.IllegalValue, info, false);
+        this.cond = cond;
+        this.label = label;
+    }
+
+    /**
+     * Creates a new LIRBranch instruction.
+     *
+     * @param cond
+     * @param kind
+     * @param block
+     *
+     */
+    public LIRBranch(Condition cond, LIRBlock block) {
+        super(LIROpcode.Branch, CiValue.IllegalValue, block.debugInfo(), false);
+        this.cond = cond;
+        this.label = block.label();
+        this.block = block;
+        this.unorderedBlock = null;
+    }
+
+    public LIRBranch(Condition cond, LIRBlock block, LIRBlock ublock) {
+        super(LIROpcode.CondFloatBranch, CiValue.IllegalValue, (block.debugInfo() != null ? block.debugInfo() : (ublock != null ? ublock.debugInfo() : null)), false);
+        this.cond = cond;
+        this.label = block.label();
+        this.block = block;
+        this.unorderedBlock = ublock;
+    }
+
+    /**
+     * @return the condition
+     */
+    public Condition cond() {
+        return cond;
+    }
+
+    public Label label() {
+        return label;
+    }
+
+    public LIRBlock block() {
+        return block;
+    }
+
+    public LIRBlock unorderedBlock() {
+        return unorderedBlock;
+    }
+
+    public void changeBlock(LIRBlock b) {
+        assert block != null : "must have old block";
+        assert block.label() == label() : "must be equal";
+        assert b != null;
+
+        this.block = b;
+        this.label = b.label();
+    }
+
+    public void negateCondition() {
+        cond = cond.negate();
+    }
+
+    @Override
+    public void emitCode(LIRAssembler masm) {
+        masm.emitBranch(this);
+    }
+
+    @Override
+    public String operationString(OperandFormatter operandFmt) {
+        StringBuilder buf = new StringBuilder(cond().operator).append(' ');
+        if (block() != null) {
+            buf.append("[B").append(block.blockID()).append(']');
+        } else if (label().isBound()) {
+            buf.append("[label:0x").append(Integer.toHexString(label().position())).append(']');
+        } else {
+            buf.append("[label:??]");
+        }
+        if (unorderedBlock() != null) {
+            buf.append("unordered: [B").append(unorderedBlock().blockID()).append(']');
+        }
+        return buf.toString();
+    }
+
+    public void substitute(LIRBlock oldBlock, LIRBlock newBlock) {
+        assert newBlock != null;
+        if (block == oldBlock) {
+            block = newBlock;
+            LIRInstruction instr = newBlock.lir().instructionsList().get(0);
+            assert instr instanceof LIRLabel : "first instruction of block must be label";
+            label = ((LIRLabel) instr).label();
+        }
+        if (unorderedBlock == oldBlock) {
+            unorderedBlock = newBlock;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRCall.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.lir;
+
+import java.util.*;
+
+import com.sun.cri.ci.*;
+import com.sun.cri.ci.CiTargetMethod.*;
+import com.sun.cri.ri.*;
+import com.sun.cri.xir.CiXirAssembler.*;
+
+/**
+ * This class represents a call instruction; either to a {@linkplain CiRuntimeCall runtime method},
+ * a {@linkplain RiMethod Java method}, a native function or a global stub.
+ *
+ * @author Marcelo Cintra
+ */
+public class LIRCall extends LIRInstruction {
+
+    /**
+     * The target of the call. This will be a {@link CiRuntimeCall}, {@link RiMethod} or {@link CiValue}
+     * object denoting a call to the runtime, a Java method or a native function respectively.
+     */
+    public final Object target;
+    /**
+     * The call site needs to be marked if this is non-null.
+     */
+    public final Map<XirMark, Mark> marks;
+
+    private final int targetAddressIndex;
+
+    public final List<CiValue> pointerSlots;
+
+
+    private static CiValue[] toArray(List<CiValue> arguments) {
+        return arguments.toArray(new CiValue[arguments.size()]);
+    }
+
+    public LIRCall(LIROpcode opcode,
+                   Object target,
+                   CiValue result,
+                   List<CiValue> arguments,
+                   LIRDebugInfo info,
+                   Map<XirMark, Mark> marks,
+                   boolean calleeSaved,
+                   List<CiValue> pointerSlots) {
+        super(opcode, result, info, !calleeSaved, 0, 0, toArray(arguments));
+        this.marks = marks;
+        this.pointerSlots = pointerSlots;
+        if (opcode == LIROpcode.DirectCall) {
+            this.targetAddressIndex = -1;
+        } else {
+            // The last argument is the operand holding the address for the indirect call
+            this.targetAddressIndex = arguments.size() - 1;
+        }
+        this.target = target;
+    }
+
+    /**
+     * Emits target assembly code for this instruction.
+     *
+     * @param masm the target assembler
+     */
+    @Override
+    public void emitCode(LIRAssembler masm) {
+        masm.emitCall(this);
+    }
+
+    /**
+     * Returns the receiver for this method call.
+     * @return the receiver
+     */
+    public CiValue receiver() {
+        return operand(0);
+    }
+
+    public RiMethod method() {
+        return (RiMethod) target;
+    }
+
+    public CiRuntimeCall runtimeCall() {
+        return (CiRuntimeCall) target;
+    }
+
+    public CiValue targetAddress() {
+        if (targetAddressIndex >= 0) {
+            return operand(targetAddressIndex);
+        }
+        return null;
+    }
+
+    @Override
+    public String operationString(OperandFormatter operandFmt) {
+        StringBuilder buf = new StringBuilder();
+        if (result().isLegal()) {
+            buf.append(operandFmt.format(result())).append(" = ");
+        }
+        String targetAddress = null;
+        if (code == LIROpcode.RuntimeCall) {
+            buf.append(target);
+        } else if (code != LIROpcode.DirectCall && code != LIROpcode.ConstDirectCall) {
+            if (targetAddressIndex >= 0) {
+                targetAddress = operandFmt.format(targetAddress());
+                buf.append(targetAddress);
+            }
+        }
+        buf.append('(');
+        boolean first = true;
+        for (LIROperand operandSlot : operands) {
+            String operand = operandFmt.format(operandSlot.value(this));
+            if (!operand.isEmpty() && !operand.equals(targetAddress)) {
+                if (!first) {
+                    buf.append(", ");
+                } else {
+                    first = false;
+                }
+                buf.append(operand);
+            }
+        }
+        buf.append(')');
+        return buf.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRCompareAndSwap.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.lir;
+
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code LIRCompareAndSwap} class definition.
+ *
+ * @author Marcelo Cintra
+ *
+ */
+public class LIRCompareAndSwap extends LIRInstruction {
+
+    /**
+     * Constructs a new LIRCompareAndSwap instruction.
+     * @param addr
+     * @param expectedValue
+     * @param newValue
+     */
+    public LIRCompareAndSwap(LIROpcode opcode, CiValue addr, CiValue expectedValue, CiValue newValue) {
+        super(opcode, CiValue.IllegalValue, null, false, 0, 0, addr, expectedValue, newValue);
+    }
+
+    /**
+     * Gets the address of compare and swap.
+     *
+     * @return the address
+     */
+    public CiValue address() {
+        return operand(0);
+    }
+
+    /**
+     * Gets the cmpValue of this class.
+     *
+     * @return the cmpValue
+     */
+    public CiValue expectedValue() {
+        return operand(1);
+    }
+
+    /**
+     * Gets the newValue of this class.
+     *
+     * @return the newValue
+     */
+    public CiValue newValue() {
+        return operand(2);
+    }
+
+    /**
+     * Emits target assembly code for this instruction.
+     *
+     * @param masm the target assembler
+     */
+    @Override
+    public void emitCode(LIRAssembler masm) {
+        masm.emitCompareAndSwap(this);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRConvert.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.lir;
+
+import com.oracle.max.graal.compiler.globalstub.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code LIRConvert} class definition.
+ *
+ * @author Marcelo Cintra
+ *
+ */
+public class LIRConvert extends LIROp1 {
+
+    public final int bytecode;
+    public GlobalStub globalStub;
+
+    /**
+     * Constructs a new instruction LIRConvert for a given operand.
+     *
+     * @param bytecode the opcode of the bytecode for this conversion
+     * @param operand the input operand for this instruction
+     * @param result the result operand for this instruction
+     */
+    public LIRConvert(int bytecode, CiValue operand, CiValue result) {
+        super(LIROpcode.Convert, operand, result);
+        this.bytecode = bytecode;
+    }
+
+    /**
+     * Emits target assembly code for this LIRConvert instruction.
+     *
+     * @param masm the LIRAssembler
+     */
+    @Override
+    public void emitCode(LIRAssembler masm) {
+        masm.emitConvert(this);
+    }
+
+    /**
+     * Prints this instruction to a LogStream.
+     */
+    @Override
+    public String operationString(OperandFormatter operandFmt) {
+        return "[" + Bytecodes.nameOf(bytecode) + "] " + super.operationString(operandFmt);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRDebugInfo.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.lir;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.value.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+/**
+ * This class represents debugging and deoptimization information attached to a LIR instruction.
+ */
+public class LIRDebugInfo {
+
+    public abstract static class ValueLocator {
+        public abstract CiValue getLocation(Value value);
+    }
+
+    public final FrameState state;
+    private LIRBlock exceptionEdge;
+    public CiDebugInfo debugInfo;
+
+    public LIRDebugInfo(FrameState state) {
+        assert state != null;
+        this.state = state;
+    }
+
+    public LIRBlock exceptionEdge() {
+        return exceptionEdge;
+    }
+
+    public void setExceptionEdge(LIRBlock exceptionEdge) {
+        this.exceptionEdge = exceptionEdge;
+    }
+
+    private LIRDebugInfo(LIRDebugInfo info) {
+        this.state = info.state;
+        this.exceptionEdge = info.exceptionEdge;
+    }
+
+    public LIRDebugInfo copy() {
+        return new LIRDebugInfo(this);
+    }
+
+    public void setOop(CiValue location, GraalCompilation compilation, BitMap frameRefMap, BitMap regRefMap) {
+        CiTarget target = compilation.target;
+        if (location.isAddress()) {
+            CiAddress stackLocation = (CiAddress) location;
+            assert stackLocation.index.isIllegal();
+            if (stackLocation.base == CiRegister.Frame.asValue()) {
+                int offset = stackLocation.displacement;
+                assert offset % target.wordSize == 0 : "must be aligned";
+                int stackMapIndex = offset / target.wordSize;
+                setBit(frameRefMap, stackMapIndex);
+            }
+        } else if (location.isStackSlot()) {
+            CiStackSlot stackSlot = (CiStackSlot) location;
+            assert !stackSlot.inCallerFrame();
+            assert target.spillSlotSize == target.wordSize;
+            setBit(frameRefMap, stackSlot.index());
+        } else {
+            assert location.isRegister() : "objects can only be in a register";
+            CiRegisterValue registerLocation = (CiRegisterValue) location;
+            int reg = registerLocation.reg.number;
+            assert reg >= 0 : "object cannot be in non-object register " + registerLocation.reg;
+            assert reg < target.arch.registerReferenceMapBitCount;
+            setBit(regRefMap, reg);
+        }
+    }
+
+    public CiDebugInfo debugInfo() {
+        assert debugInfo != null : "debug info not allocated yet";
+        return debugInfo;
+    }
+
+    public boolean hasDebugInfo() {
+        return debugInfo != null;
+    }
+
+    public static void setBit(BitMap refMap, int bit) {
+        assert !refMap.get(bit) : "Ref map entry " + bit + " is already set.";
+        refMap.set(bit);
+    }
+
+    @Override
+    public String toString() {
+        return state.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRInstruction.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,552 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.lir;
+
+import static com.oracle.max.graal.compiler.GraalCompilation.*;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.lir.LIROperand.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code LIRInstruction} class definition.
+ *
+ * @author Marcelo Cintra
+ * @author Thomas Wuerthinger
+ */
+public abstract class LIRInstruction {
+
+    private static final LIROperand ILLEGAL_SLOT = new LIROperand(CiValue.IllegalValue);
+
+    private static final CiValue[] NO_OPERANDS = {};
+
+    public static final OperandMode[] OPERAND_MODES = OperandMode.values();
+
+    /**
+     * Constants denoting how a LIR instruction uses an operand. Any combination of these modes
+     * can be applied to an operand as long as every operand has at least one mode applied to it.
+     */
+    public enum OperandMode {
+        /**
+         * An operand that is defined by a LIR instruction and is live after the code emitted for a LIR instruction.
+         */
+        Output,
+
+        /**
+         * An operand that is used by a LIR instruction and is live before the code emitted for a LIR instruction.
+         * Unless such an operand is also an output or temp operand, it must not be modified by a LIR instruction.
+         */
+        Input,
+
+        /**
+         * An operand that is both modified and used by a LIR instruction.
+         */
+        Temp
+    }
+
+    /**
+     * The opcode of this instruction.
+     */
+    public final LIROpcode code;
+
+    /**
+     * The result operand for this instruction.
+     */
+    private final LIROperand result;
+
+    /**
+     * The input and temporary operands of this instruction.
+     */
+    protected final LIROperand[] operands;
+
+    /**
+     * Used to emit debug information.
+     */
+    public final LIRDebugInfo info;
+
+    /**
+     * Value id for register allocation.
+     */
+    private int id;
+
+    /**
+     * Determines if all caller-saved registers are destroyed by this instruction.
+     */
+    public final boolean hasCall;
+
+    /**
+     * The number of variable or register output operands for this instruction.
+     * These operands are at indexes {@code [0 .. allocatorOutputCount-1]} in {@link #allocatorOperands}.
+     *
+     * @see OperandMode#Output
+     */
+    private byte allocatorOutputCount;
+
+    /**
+     * The number of variable or register input operands for this instruction.
+     * These operands are at indexes {@code [allocatorOutputCount .. (allocatorInputCount+allocatorOutputCount-1)]} in {@link #allocatorOperands}.
+     *
+     * @see OperandMode#Input
+     */
+    private byte allocatorInputCount;
+
+    /**
+     * The number of variable or register temp operands for this instruction.
+     * These operands are at indexes {@code [allocatorInputCount+allocatorOutputCount .. (allocatorTempCount+allocatorInputCount+allocatorOutputCount-1)]} in {@link #allocatorOperands}.
+     *
+     * @see OperandMode#Temp
+     */
+    private byte allocatorTempCount;
+
+    /**
+     * The number of variable or register input or temp operands for this instruction.
+     */
+    private byte allocatorTempInputCount;
+
+    /**
+     * The set of operands that must be known to the register allocator either to bind a register
+     * or stack slot to a {@linkplain CiVariable variable} or to inform the allocator about operands
+     * that are already fixed to a specific register.
+     * This set excludes all constant operands as well as operands that are bound to
+     * a stack slot in the {@linkplain CiStackSlot#inCallerFrame() caller's frame}.
+     * This array is partitioned as follows.
+     * <pre>
+     *
+     *   <-- allocatorOutputCount --> <-- allocatorInputCount --> <-- allocatorTempCount -->
+     *  +----------------------------+---------------------------+--------------------------+
+     *  |       output operands      |       input operands      |      temp operands       |
+     *  +----------------------------+---------------------------+--------------------------+
+     *
+     * </pre>
+     */
+    final List<CiValue> allocatorOperands;
+
+    /**
+     * Constructs a new LIR instruction that has no input or temp operands.
+     *
+     * @param opcode the opcode of the new instruction
+     * @param result the operand that holds the operation result of this instruction. This will be
+     *            {@link CiValue#IllegalValue} for instructions that do not produce a result.
+     * @param info the {@link LIRDebugInfo} info that is to be preserved for the instruction. This will be {@code null} when no debug info is required for the instruction.
+     * @param hasCall specifies if all caller-saved registers are destroyed by this instruction
+     */
+    public LIRInstruction(LIROpcode opcode, CiValue result, LIRDebugInfo info, boolean hasCall) {
+        this(opcode, result, info, hasCall, 0, 0, NO_OPERANDS);
+    }
+
+    /**
+     * Constructs a new LIR instruction. The {@code operands} array is partitioned as follows:
+     * <pre>
+     *
+     *                              <------- tempInput -------> <--------- temp --------->
+     *  +--------------------------+---------------------------+--------------------------+
+     *  |       input operands     |   input+temp operands     |      temp operands       |
+     *  +--------------------------+---------------------------+--------------------------+
+     *
+     * </pre>
+     *
+     * @param opcode the opcode of the new instruction
+     * @param result the operand that holds the operation result of this instruction. This will be
+     *            {@link CiValue#IllegalValue} for instructions that do not produce a result.
+     * @param info the {@link LIRDebugInfo} that is to be preserved for the instruction. This will be {@code null} when no debug info is required for the instruction.
+     * @param hasCall specifies if all caller-saved registers are destroyed by this instruction
+     * @param tempInput the number of operands that are both {@linkplain OperandMode#Input input} and {@link OperandMode#Temp temp} operands for this instruction
+     * @param temp the number of operands that are {@link OperandMode#Temp temp} operands for this instruction
+     * @param operands the input and temp operands for the instruction
+     */
+    public LIRInstruction(LIROpcode opcode, CiValue result, LIRDebugInfo info, boolean hasCall, int tempInput, int temp, CiValue... operands) {
+        this.code = opcode;
+        this.info = info;
+        this.hasCall = hasCall;
+
+        assert opcode != LIROpcode.Move || result != CiValue.IllegalValue;
+        allocatorOperands = new ArrayList<CiValue>(operands.length + 3);
+        this.result = initOutput(result);
+
+        GraalMetrics.LIRInstructions++;
+
+        if (opcode == LIROpcode.Move) {
+            GraalMetrics.LIRMoveInstructions++;
+        }
+        id = -1;
+        this.operands = new LIROperand[operands.length];
+        initInputsAndTemps(tempInput, temp, operands);
+
+        assert verifyOperands();
+    }
+
+    public final int id() {
+        return id;
+    }
+
+    public final void setId(int id) {
+        this.id = id;
+    }
+
+    private LIROperand initOutput(CiValue output) {
+        assert output != null;
+        if (output != CiValue.IllegalValue) {
+            if (output.isAddress()) {
+                return addAddress((CiAddress) output);
+            }
+            if (output.isStackSlot()) {
+                return new LIROperand(output);
+            }
+
+            assert allocatorOperands.size() == allocatorOutputCount;
+            allocatorOperands.add(output);
+            allocatorOutputCount++;
+            return new LIRVariableOperand(allocatorOperands.size() - 1);
+        } else {
+            return ILLEGAL_SLOT;
+        }
+    }
+
+    /**
+     * Adds a {@linkplain CiValue#isLegal() legal} value that is part of an address to
+     * the list of {@linkplain #allocatorOperands register allocator operands}. If
+     * the value is {@linkplain CiVariable variable}, then its index into the list
+     * of register allocator operands is returned. Otherwise, {@code -1} is returned.
+     */
+    private int addAddressPart(CiValue part) {
+        if (part.isRegister()) {
+            allocatorInputCount++;
+            allocatorOperands.add(part);
+            return -1;
+        }
+        if (part.isVariable()) {
+            allocatorInputCount++;
+            allocatorOperands.add(part);
+            return allocatorOperands.size() - 1;
+        }
+        assert part.isIllegal();
+        return -1;
+    }
+
+    private LIROperand addAddress(CiAddress address) {
+        assert address.base.isVariableOrRegister();
+
+        int base = addAddressPart(address.base);
+        int index = addAddressPart(address.index);
+
+        if (base != -1 || index != -1) {
+            return new LIRAddressOperand(base, index, address);
+        }
+
+        assert address.base.isRegister() && (address.index.isIllegal() || address.index.isRegister());
+        return new LIROperand(address);
+    }
+
+    private LIROperand addOperand(CiValue operand, boolean isInput, boolean isTemp) {
+        assert operand != null;
+        if (operand != CiValue.IllegalValue) {
+            assert !(operand.isAddress());
+            if (operand.isStackSlot()) {
+                // no variables to add
+                return new LIROperand(operand);
+            } else if (operand.isConstant()) {
+                // no variables to add
+                return new LIROperand(operand);
+            } else {
+                assert allocatorOperands.size() == allocatorOutputCount + allocatorInputCount + allocatorTempInputCount + allocatorTempCount;
+                allocatorOperands.add(operand);
+
+                if (isInput && isTemp) {
+                    allocatorTempInputCount++;
+                } else if (isInput) {
+                    allocatorInputCount++;
+                } else {
+                    assert isTemp;
+                    allocatorTempCount++;
+                }
+
+                return new LIRVariableOperand(allocatorOperands.size() - 1);
+            }
+        } else {
+            return ILLEGAL_SLOT;
+        }
+    }
+
+    /**
+     * Gets an input or temp operand of this instruction.
+     *
+     * @param index the index of the operand requested
+     * @return the {@code index}'th operand
+     */
+    public final CiValue operand(int index) {
+        if (index >= operands.length) {
+            return CiValue.IllegalValue;
+        }
+
+        return operands[index].value(this);
+    }
+
+    private void initInputsAndTemps(int tempInputCount, int tempCount, CiValue[] operands) {
+
+        // Addresses in instruction
+        for (int i = 0; i < operands.length; i++) {
+            CiValue op = operands[i];
+            if (op.isAddress()) {
+                this.operands[i] = addAddress((CiAddress) op);
+            }
+        }
+
+        int z = 0;
+        // Input-only operands
+        for (int i = 0; i < operands.length - tempInputCount - tempCount; i++) {
+            if (this.operands[z] == null) {
+                this.operands[z] = addOperand(operands[z], true, false);
+            }
+            z++;
+        }
+
+        // Operands that are both inputs and temps
+        for (int i = 0; i < tempInputCount; i++) {
+            if (this.operands[z] == null) {
+                this.operands[z] = addOperand(operands[z], true, true);
+            }
+            z++;
+        }
+
+        // Temp-only operands
+        for (int i = 0; i < tempCount; i++) {
+            if (this.operands[z] == null) {
+                this.operands[z] = addOperand(operands[z], false, true);
+            }
+            z++;
+        }
+    }
+
+    private boolean verifyOperands() {
+        for (LIROperand operandSlot : operands) {
+            assert operandSlot != null;
+        }
+
+        for (CiValue operand : this.allocatorOperands) {
+            assert operand != null;
+            assert operand.isVariableOrRegister() : "LIR operands can only be variables and registers initially, not " + operand.getClass().getSimpleName();
+        }
+        return true;
+    }
+
+    /**
+     * Gets the result operand for this instruction.
+     *
+     * @return return the result operand
+     */
+    public final CiValue result() {
+        return result.value(this);
+    }
+
+    /**
+     * Gets the instruction name.
+     *
+     * @return the name of the enum constant that represents the instruction opcode, exactly as declared in the enum
+     *         LIROpcode declaration.
+     */
+    public String name() {
+        return code.name();
+    }
+
+    /**
+     * Abstract method to be used to emit target code for this instruction.
+     *
+     * @param masm the target assembler.
+     */
+    public abstract void emitCode(LIRAssembler masm);
+
+    /**
+     * Utility for specializing how a {@linkplain CiValue LIR operand} is formatted to a string.
+     * The {@linkplain OperandFormatter#DEFAULT default formatter} returns the value of
+     * {@link CiValue#toString()}.
+     */
+    public static class OperandFormatter {
+        public static final OperandFormatter DEFAULT = new OperandFormatter();
+
+        /**
+         * Formats a given operand as a string.
+         *
+         * @param operand the operand to format
+         * @return {@code operand} as a string
+         */
+        public String format(CiValue operand) {
+            return operand.toString();
+        }
+    }
+
+    /**
+     * Gets the operation performed by this instruction in terms of its operands as a string.
+     */
+    public String operationString(OperandFormatter operandFmt) {
+        StringBuilder buf = new StringBuilder();
+        if (result != ILLEGAL_SLOT) {
+            buf.append(operandFmt.format(result.value(this))).append(" = ");
+        }
+        if (operands.length > 1) {
+            buf.append("(");
+        }
+        boolean first = true;
+        for (LIROperand operandSlot : operands) {
+            String operand = operandFmt.format(operandSlot.value(this));
+            if (!operand.isEmpty()) {
+                if (!first) {
+                    buf.append(", ");
+                } else {
+                    first = false;
+                }
+                buf.append(operand);
+            }
+        }
+        if (operands.length > 1) {
+            buf.append(")");
+        }
+        return buf.toString();
+    }
+
+    public boolean verify() {
+        return true;
+    }
+
+    /**
+     * Determines if a given opcode is in a given range of valid opcodes.
+     *
+     * @param opcode the opcode to be tested.
+     * @param start the lower bound range limit of valid opcodes
+     * @param end the upper bound range limit of valid opcodes
+     */
+    protected static boolean isInRange(LIROpcode opcode, LIROpcode start, LIROpcode end) {
+        return start.ordinal() < opcode.ordinal() && opcode.ordinal() < end.ordinal();
+    }
+
+    public boolean hasOperands() {
+        if (info != null || hasCall) {
+            return true;
+        }
+        return allocatorOperands.size() > 0;
+    }
+
+    public final int operandCount(OperandMode mode) {
+        if (mode == OperandMode.Output) {
+            return allocatorOutputCount;
+        } else if (mode == OperandMode.Input) {
+            return allocatorInputCount + allocatorTempInputCount;
+        } else {
+            assert mode == OperandMode.Temp;
+            return allocatorTempInputCount + allocatorTempCount;
+        }
+    }
+
+    public final CiValue operandAt(OperandMode mode, int index) {
+        if (mode == OperandMode.Output) {
+            assert index < allocatorOutputCount;
+            return allocatorOperands.get(index);
+        } else if (mode == OperandMode.Input) {
+            assert index < allocatorInputCount + allocatorTempInputCount;
+            return allocatorOperands.get(index + allocatorOutputCount);
+        } else {
+            assert mode == OperandMode.Temp;
+            assert index < allocatorTempInputCount + allocatorTempCount;
+            return allocatorOperands.get(index + allocatorOutputCount + allocatorInputCount);
+        }
+    }
+
+    public final void setOperandAt(OperandMode mode, int index, CiValue location) {
+        assert index < operandCount(mode);
+        assert location.kind != CiKind.Illegal;
+        assert operandAt(mode, index).isVariable();
+        if (mode == OperandMode.Output) {
+            assert index < allocatorOutputCount;
+            allocatorOperands.set(index, location);
+        } else if (mode == OperandMode.Input) {
+            assert index < allocatorInputCount + allocatorTempInputCount;
+            allocatorOperands.set(index + allocatorOutputCount, location);
+        } else {
+            assert mode == OperandMode.Temp;
+            assert index < allocatorTempInputCount + allocatorTempCount;
+            allocatorOperands.set(index + allocatorOutputCount + allocatorInputCount, location);
+        }
+    }
+
+    public final LIRBlock exceptionEdge() {
+        return (info == null) ? null : info.exceptionEdge();
+    }
+
+    @Override
+    public String toString() {
+        return toString(OperandFormatter.DEFAULT);
+    }
+
+    public final String toStringWithIdPrefix() {
+        if (id != -1) {
+            return String.format("%4d %s", id, toString());
+        }
+        return "     " + toString();
+    }
+
+    protected static String refMapToString(CiDebugInfo debugInfo, OperandFormatter operandFmt) {
+        StringBuilder buf = new StringBuilder();
+        if (debugInfo.hasStackRefMap()) {
+            BitMap bm = debugInfo.frameRefMap;
+            for (int slot = bm.nextSetBit(0); slot >= 0; slot = bm.nextSetBit(slot + 1)) {
+                if (buf.length() != 0) {
+                    buf.append(", ");
+                }
+                buf.append(operandFmt.format(CiStackSlot.get(CiKind.Object, slot)));
+            }
+        }
+        if (debugInfo.hasRegisterRefMap()) {
+            BitMap bm = debugInfo.registerRefMap;
+            for (int reg = bm.nextSetBit(0); reg >= 0; reg = bm.nextSetBit(reg + 1)) {
+                if (buf.length() != 0) {
+                    buf.append(", ");
+                }
+                CiRegisterValue register = compilation().target.arch.registers[reg].asValue(CiKind.Object);
+                buf.append(operandFmt.format(register));
+            }
+        }
+        return buf.toString();
+    }
+
+    protected void appendDebugInfo(StringBuilder buf, OperandFormatter operandFmt, LIRDebugInfo info) {
+        if (info != null) {
+            buf.append(" [bci:").append(info.state.bci);
+            if (info.hasDebugInfo()) {
+                CiDebugInfo debugInfo = info.debugInfo();
+                String refmap = refMapToString(debugInfo, operandFmt);
+                if (refmap.length() != 0) {
+                    buf.append(", refmap(").append(refmap.trim()).append(')');
+                }
+            }
+            buf.append(']');
+        }
+    }
+
+    public String toString(OperandFormatter operandFmt) {
+        StringBuilder buf = new StringBuilder(name()).append(' ').append(operationString(operandFmt));
+        appendDebugInfo(buf, operandFmt, info);
+        return buf.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRLabel.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.lir;
+
+import com.oracle.max.asm.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code LIRLabel} class definition.
+ *
+ * @author Marcelo Cintra
+ */
+public class LIRLabel extends LIROp0 {
+
+    private Label label;
+
+    /**
+     * Constructs a LIRLabel instruction.
+     * @param label the label
+     */
+    public LIRLabel(Label label) {
+        super(LIROpcode.Label, CiValue.IllegalValue, null);
+        assert label != null;
+        this.label = label;
+    }
+
+    /**
+     * Gets the label associated to this instruction.
+     * @return the label
+     */
+    public Label label() {
+        return label;
+    }
+
+    /**
+     * Emits target assembly code for this LIRLabel instruction.
+     * @param masm the LIRAssembler
+     */
+    @Override
+    public void emitCode(LIRAssembler masm) {
+        masm.emitOpLabel(this);
+    }
+
+    /**
+     * Prints this instruction to a LogStream.
+     */
+    @Override
+    public String operationString(OperandFormatter operandFmt) {
+        return label.isBound() ? String.valueOf(label.position()) : "?";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRList.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,479 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.lir;
+
+import java.util.*;
+
+import com.oracle.max.asm.*;
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.alloc.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.compiler.globalstub.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ci.CiTargetMethod.*;
+import com.sun.cri.ri.*;
+import com.sun.cri.xir.*;
+import com.sun.cri.xir.CiXirAssembler.*;
+
+/**
+ * This class represents a list of LIR instructions and contains factory methods for creating and appending LIR
+ * instructions to this list.
+ */
+public final class LIRList {
+
+    private List<LIRInstruction> operations;
+    private final LIRGenerator generator;
+
+    private final LIROpcode runtimeCallOp;
+
+    private LIROpcode directCallOp(RiMethod method) {
+        return GraalOptions.UseConstDirectCall && method.hasCompiledCode() ? LIROpcode.ConstDirectCall : LIROpcode.DirectCall;
+    }
+
+    public LIRList(LIRGenerator generator) {
+        this.generator = generator;
+        this.operations = new ArrayList<LIRInstruction>(8);
+        runtimeCallOp = GraalOptions.UseConstDirectCall ? LIROpcode.ConstDirectCall : LIROpcode.DirectCall;
+    }
+
+    private void append(LIRInstruction op) {
+        if (GraalOptions.PrintIRWithLIR && !TTY.isSuppressed()) {
+            generator.maybePrintCurrentInstruction();
+            TTY.println(op.toStringWithIdPrefix());
+            TTY.println();
+        }
+        operations.add(op);
+        assert op.verify();
+    }
+
+    public List<LIRInstruction> instructionsList() {
+        return operations;
+    }
+
+    public int length() {
+        return operations.size();
+    }
+
+    public LIRInstruction at(int i) {
+        return operations.get(i);
+    }
+
+    public void callDirect(RiMethod method, CiValue result, List<CiValue> arguments, LIRDebugInfo info, Map<XirMark, Mark> marks, List<CiValue> pointerSlots) {
+        append(new LIRCall(directCallOp(method), method, result, arguments, info, marks, false, pointerSlots));
+    }
+
+    public void callIndirect(RiMethod method, CiValue result, List<CiValue> arguments, LIRDebugInfo info, Map<XirMark, Mark> marks, List<CiValue> pointerSlots) {
+        append(new LIRCall(LIROpcode.IndirectCall, method, result, arguments, info, marks, false, pointerSlots));
+    }
+
+    public void callNative(String symbol, CiValue result, List<CiValue> arguments, LIRDebugInfo info, Map<XirMark, Mark> marks) {
+        append(new LIRCall(LIROpcode.NativeCall, symbol, result, arguments, info, marks, false, null));
+    }
+
+    public void templateCall(CiValue result, List<CiValue> arguments) {
+        append(new LIRCall(LIROpcode.TemplateCall, null, result, arguments, null, null, false, null));
+    }
+
+    public void membar(int barriers) {
+        append(new LIRMemoryBarrier(barriers));
+    }
+
+    public void branchDestination(Label lbl) {
+        append(new LIRLabel(lbl));
+    }
+
+    public void negate(CiValue src, CiValue dst, GlobalStub globalStub) {
+        LIRNegate op = new LIRNegate(src, dst);
+        op.globalStub = globalStub;
+        append(op);
+    }
+
+    public void lea(CiValue src, CiValue dst) {
+        append(new LIROp1(LIROpcode.Lea, src, dst));
+    }
+
+    public void unalignedMove(CiValue src, CiValue dst) {
+        append(new LIROp1(LIROp1.LIRMoveKind.Unaligned, src, dst, dst.kind, null));
+    }
+
+    public void move(CiAddress src, CiValue dst, LIRDebugInfo info) {
+        append(new LIROp1(LIROpcode.Move, src, dst, src.kind, info));
+    }
+
+    public void move(CiValue src, CiAddress dst, LIRDebugInfo info) {
+        append(new LIROp1(LIROpcode.Move, src, dst, dst.kind, info));
+    }
+
+    public void move(CiValue src, CiValue dst, CiKind kind) {
+        append(new LIROp1(LIROpcode.Move, src, dst, kind, null));
+    }
+
+    public void move(CiValue src, CiValue dst) {
+        append(new LIROp1(LIROpcode.Move, src, dst, dst.kind, null));
+    }
+
+    public void volatileMove(CiValue src, CiValue dst, CiKind kind, LIRDebugInfo info) {
+        append(new LIROp1(LIROp1.LIRMoveKind.Volatile, src, dst, kind, info));
+    }
+
+    public void oop2reg(Object o, CiValue reg) {
+        append(new LIROp1(LIROpcode.Move, CiConstant.forObject(o), reg));
+    }
+
+    public void returnOp(CiValue result) {
+        append(new LIROp1(LIROpcode.Return, result));
+    }
+
+    public void monitorAddress(int monitor, CiValue dst) {
+        append(new LIRMonitorAddress(dst, monitor));
+    }
+
+    public void convert(int code, CiValue left, CiValue dst, GlobalStub globalStub) {
+        LIRConvert op = new LIRConvert(code, left, dst);
+        op.globalStub = globalStub;
+        append(op);
+    }
+
+    public void logicalAnd(CiValue left, CiValue right, CiValue dst) {
+        append(new LIROp2(LIROpcode.LogicAnd, left, right, dst));
+    }
+
+    public void logicalOr(CiValue left, CiValue right, CiValue dst) {
+        append(new LIROp2(LIROpcode.LogicOr, left, right, dst));
+    }
+
+    public void logicalXor(CiValue left, CiValue right, CiValue dst) {
+        append(new LIROp2(LIROpcode.LogicXor, left, right, dst));
+    }
+
+    public void nullCheck(CiValue opr, LIRDebugInfo info) {
+        append(new LIROp1(LIROpcode.NullCheck, opr, info));
+    }
+
+    public void compareTo(CiValue left, CiValue right, CiValue dst) {
+        append(new LIROp2(LIROpcode.CompareTo, left, right, dst));
+    }
+
+    public void cmp(Condition condition, CiValue left, CiValue right, LIRDebugInfo info) {
+        append(new LIROp2(LIROpcode.Cmp, condition, left, right, info));
+    }
+
+    public void cmp(Condition condition, CiValue left, CiValue right) {
+        cmp(condition, left, right, null);
+    }
+
+    public void cmp(Condition condition, CiValue left, int right, LIRDebugInfo info) {
+        cmp(condition, left, CiConstant.forInt(right), info);
+    }
+
+    public void cmp(Condition condition, CiValue left, int right) {
+        cmp(condition, left, right, null);
+    }
+
+    public void cmove(Condition condition, CiValue src1, CiValue src2, CiValue dst) {
+        append(new LIROp2(LIROpcode.Cmove, condition, src1, src2, dst));
+    }
+
+    public void abs(CiValue from, CiValue to, CiValue tmp) {
+        append(new LIROp2(LIROpcode.Abs, from, tmp, to));
+    }
+
+    public void sqrt(CiValue from, CiValue to, CiValue tmp) {
+        append(new LIROp2(LIROpcode.Sqrt, from, tmp, to));
+    }
+
+    public void log(CiValue from, CiValue to, CiValue tmp) {
+        append(new LIROp2(LIROpcode.Log, from, tmp, to));
+    }
+
+    public void log10(CiValue from, CiValue to, CiValue tmp) {
+        append(new LIROp2(LIROpcode.Log10, from, tmp, to));
+    }
+
+    public void sin(CiValue from, CiValue to, CiValue tmp1, CiValue tmp2) {
+        append(new LIROp2(LIROpcode.Sin, from, tmp1, to, tmp2));
+    }
+
+    public void cos(CiValue from, CiValue to, CiValue tmp1, CiValue tmp2) {
+        append(new LIROp2(LIROpcode.Cos, from, tmp1, to, tmp2));
+    }
+
+    public void tan(CiValue from, CiValue to, CiValue tmp1, CiValue tmp2) {
+        append(new LIROp2(LIROpcode.Tan, from, tmp1, to, tmp2));
+    }
+
+    public void add(CiValue left, CiValue right, CiValue res) {
+        append(new LIROp2(LIROpcode.Add, left, right, res));
+    }
+
+    public void sub(CiValue left, CiValue right, CiValue res) {
+        append(new LIROp2(LIROpcode.Sub, left, right, res));
+    }
+
+    public void mul(CiValue left, CiValue right, CiValue res) {
+        append(new LIROp2(LIROpcode.Mul, left, right, res));
+    }
+
+    public void div(CiValue left, CiValue right, CiValue res, LIRDebugInfo info) {
+        append(new LIROp2(LIROpcode.Div, left, right, res, info));
+    }
+
+    public void rem(CiValue left, CiValue right, CiValue res, LIRDebugInfo info) {
+        append(new LIROp2(LIROpcode.Rem, left, right, res, info));
+    }
+
+    public void jump(LIRBlock block) {
+        assert block != null;
+        append(new LIRBranch(Condition.TRUE, block));
+    }
+
+    public void branch(Condition cond, Label lbl) {
+        append(new LIRBranch(cond, lbl));
+    }
+
+    public void branch(Condition cond, Label lbl, LIRDebugInfo info) {
+        append(new LIRBranch(cond, lbl, info));
+    }
+
+    public void branch(Condition cond, LIRBlock block) {
+        append(new LIRBranch(cond, block));
+    }
+
+    public void branch(Condition cond, LIRBlock block, LIRBlock unordered) {
+        append(new LIRBranch(cond, block, unordered));
+    }
+
+    public void tableswitch(CiValue index, int lowKey, LIRBlock defaultTargets, LIRBlock[] targets) {
+        append(new LIRTableSwitch(index, lowKey, defaultTargets, targets));
+    }
+
+    public void shiftLeft(CiValue value, int count, CiValue dst) {
+        shiftLeft(value, CiConstant.forInt(count), dst, CiValue.IllegalValue);
+    }
+
+    public void shiftRight(CiValue value, int count, CiValue dst) {
+        shiftRight(value, CiConstant.forInt(count), dst, CiValue.IllegalValue);
+    }
+
+    public void lcmp2int(CiValue left, CiValue right, CiValue dst) {
+        append(new LIROp2(LIROpcode.Cmpl2i, left, right, dst));
+    }
+
+    public void callRuntime(CiRuntimeCall rtCall, CiValue result, List<CiValue> arguments, LIRDebugInfo info) {
+        append(new LIRCall(runtimeCallOp, rtCall, result, arguments, info, null, false, null));
+    }
+
+    public void breakpoint() {
+        append(new LIROp0(LIROpcode.Breakpoint));
+    }
+
+    public void prefetch(CiAddress addr, boolean isStore) {
+        append(new LIROp1(isStore ? LIROpcode.Prefetchw : LIROpcode.Prefetchr, addr));
+    }
+
+    public void idiv(CiValue left, CiValue right, CiValue res, CiValue tmp, LIRDebugInfo info) {
+        append(new LIROp3(LIROpcode.Idiv, left, right, tmp, res, info));
+    }
+
+    public void irem(CiValue left, CiValue right, CiValue res, CiValue tmp, LIRDebugInfo info) {
+        append(new LIROp3(LIROpcode.Irem, left, right, tmp, res, info));
+    }
+
+    public void ldiv(CiValue left, CiValue right, CiValue res, CiValue tmp, LIRDebugInfo info) {
+        append(new LIROp3(LIROpcode.Ldiv, left, right, tmp, res, info));
+    }
+
+    public void lrem(CiValue left, CiValue right, CiValue res, CiValue tmp, LIRDebugInfo info) {
+        append(new LIROp3(LIROpcode.Lrem, left, right, tmp, res, info));
+    }
+
+    public void lsb(CiValue src, CiValue dst) {
+        append(new LIRSignificantBit(LIROpcode.Lsb, src, dst));
+    }
+
+    public void msb(CiValue src, CiValue dst) {
+        append(new LIRSignificantBit(LIROpcode.Msb, src, dst));
+    }
+
+    public void wdiv(CiValue left, CiValue right, CiValue res, CiValue tmp, LIRDebugInfo info) {
+        append(new LIROp3(LIROpcode.Wdiv, left, right, tmp, res, info));
+    }
+
+    public void wrem(CiValue left, CiValue right, CiValue res, CiValue tmp, LIRDebugInfo info) {
+        append(new LIROp3(LIROpcode.Wrem, left, right, tmp, res, info));
+    }
+
+    public void wdivi(CiValue left, CiValue right, CiValue res, CiValue tmp, LIRDebugInfo info) {
+        append(new LIROp3(LIROpcode.Wdivi, left, right, tmp, res, info));
+    }
+
+    public void wremi(CiValue left, CiValue right, CiValue res, CiValue tmp, LIRDebugInfo info) {
+        append(new LIROp3(LIROpcode.Wremi, left, right, tmp, res, info));
+    }
+
+    public void cmpMemInt(Condition condition, CiValue base, int disp, int c, LIRDebugInfo info) {
+        append(new LIROp2(LIROpcode.Cmp, condition, new CiAddress(CiKind.Int, base, disp), CiConstant.forInt(c), info));
+    }
+
+    public void cmpRegMem(Condition condition, CiValue reg, CiAddress addr, LIRDebugInfo info) {
+        append(new LIROp2(LIROpcode.Cmp, condition, reg, addr, info));
+    }
+
+    public void shiftLeft(CiValue value, CiValue count, CiValue dst, CiValue tmp) {
+        append(new LIROp2(LIROpcode.Shl, value, count, dst, tmp));
+    }
+
+    public void shiftRight(CiValue value, CiValue count, CiValue dst, CiValue tmp) {
+        append(new LIROp2(LIROpcode.Shr, value, count, dst, tmp));
+    }
+
+    public void unsignedShiftRight(CiValue value, CiValue count, CiValue dst, CiValue tmp) {
+        append(new LIROp2(LIROpcode.Ushr, value, count, dst, tmp));
+    }
+
+    public void fcmp2int(CiValue left, CiValue right, CiValue dst, boolean isUnorderedLess) {
+        append(new LIROp2(isUnorderedLess ? LIROpcode.Ucmpfd2i : LIROpcode.Cmpfd2i, left, right, dst));
+    }
+
+    public void casLong(CiValue addr, CiValue cmpValue, CiValue newValue) {
+        // Compare and swap produces condition code "zero" if contentsOf(addr) == cmpValue,
+        // implying successful swap of newValue into addr
+        append(new LIRCompareAndSwap(LIROpcode.CasLong, addr, cmpValue, newValue));
+    }
+
+    public void casObj(CiValue addr, CiValue cmpValue, CiValue newValue) {
+        // Compare and swap produces condition code "zero" if contentsOf(addr) == cmpValue,
+        // implying successful swap of newValue into addr
+        append(new LIRCompareAndSwap(LIROpcode.CasObj, addr, cmpValue, newValue));
+    }
+
+    public void casInt(CiValue addr, CiValue cmpValue, CiValue newValue) {
+        // Compare and swap produces condition code "zero" if contentsOf(addr) == cmpValue,
+        // implying successful swap of newValue into addr
+        append(new LIRCompareAndSwap(LIROpcode.CasInt, addr, cmpValue, newValue));
+    }
+
+    public void store(CiValue src, CiAddress dst, LIRDebugInfo info) {
+        append(new LIROp1(LIROpcode.Move, src, dst, dst.kind, info));
+    }
+
+    public void load(CiAddress src, CiValue dst, LIRDebugInfo info) {
+        append(new LIROp1(LIROpcode.Move, src, dst, src.kind, info));
+    }
+
+    public static void printBlock(LIRBlock x) {
+        // print block id
+        TTY.print("B%d ", x.blockID());
+
+        // print flags
+        if (x.isLinearScanLoopHeader()) {
+            TTY.print("lh ");
+        }
+        if (x.isLinearScanLoopEnd()) {
+            TTY.print("le ");
+        }
+
+        // print block bci range
+        TTY.print("[%d, %d] ", -1, -1);
+
+        // print predecessors and successors
+        if (x.numberOfPreds() > 0) {
+            TTY.print("preds: ");
+            for (int i = 0; i < x.numberOfPreds(); i++) {
+                TTY.print("B%d ", x.predAt(i).blockID());
+            }
+        }
+
+        if (x.numberOfSux() > 0) {
+            TTY.print("sux: ");
+            for (int i = 0; i < x.numberOfSux(); i++) {
+                TTY.print("B%d ", x.suxAt(i).blockID());
+            }
+        }
+
+        TTY.println();
+    }
+
+    public static void printLIR(List<LIRBlock> blocks) {
+        if (TTY.isSuppressed()) {
+            return;
+        }
+        TTY.println("LIR:");
+        int i;
+        for (i = 0; i < blocks.size(); i++) {
+            LIRBlock bb = blocks.get(i);
+            printBlock(bb);
+            TTY.println("__id_Instruction___________________________________________");
+            bb.lir().printInstructions();
+        }
+    }
+
+    private void printInstructions() {
+        for (int i = 0; i < operations.size(); i++) {
+            TTY.println(operations.get(i).toStringWithIdPrefix());
+            TTY.println();
+        }
+        TTY.println();
+    }
+
+    public void append(LIRInsertionBuffer buffer) {
+        assert this == buffer.lirList() : "wrong lir list";
+        int n = operations.size();
+
+        if (buffer.numberOfOps() > 0) {
+            // increase size of instructions list
+            for (int i = 0; i < buffer.numberOfOps(); i++) {
+                operations.add(null);
+            }
+            // insert ops from buffer into instructions list
+            int opIndex = buffer.numberOfOps() - 1;
+            int ipIndex = buffer.numberOfInsertionPoints() - 1;
+            int fromIndex = n - 1;
+            int toIndex = operations.size() - 1;
+            for (; ipIndex >= 0; ipIndex--) {
+                int index = buffer.indexAt(ipIndex);
+                // make room after insertion point
+                while (index < fromIndex) {
+                    operations.set(toIndex--, operations.get(fromIndex--));
+                }
+                // insert ops from buffer
+                for (int i = buffer.countAt(ipIndex); i > 0; i--) {
+                    operations.set(toIndex--, buffer.opAt(opIndex--));
+                }
+            }
+        }
+
+        buffer.finish();
+    }
+
+    public void insertBefore(int i, LIRInstruction op) {
+        operations.add(i, op);
+    }
+
+    public void xir(XirSnippet snippet, CiValue[] operands, CiValue outputOperand, int tempInputCount, int tempCount, CiValue[] inputOperands, int[] operandIndices, int outputOperandIndex,
+                    LIRDebugInfo info, LIRDebugInfo infoAfter, RiMethod method, List<CiValue> pointerSlots) {
+        append(new LIRXirInstruction(snippet, operands, outputOperand, tempInputCount, tempCount, inputOperands, operandIndices, outputOperandIndex, info, infoAfter, method, pointerSlots));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRMemoryBarrier.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2010, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.lir;
+
+import com.sun.cri.bytecode.Bytecodes.*;
+import com.sun.cri.ci.*;
+
+/**
+ * LIR instruction implementing a {@linkplain MemoryBarriers memory barrier}.
+ *
+ * @author Doug Simon
+ */
+public class LIRMemoryBarrier extends LIRInstruction {
+
+    public final int barriers;
+
+    public LIRMemoryBarrier(int barriers) {
+        super(LIROpcode.Membar, CiValue.IllegalValue, null, false);
+        this.barriers = barriers;
+    }
+
+    @Override
+    public void emitCode(LIRAssembler masm) {
+        masm.emitMemoryBarriers(barriers);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRMonitorAddress.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2010, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.lir;
+
+import com.sun.cri.ci.*;
+
+/**
+ * LIR instruction used in to represent the address of a monitor object within the stack frame.
+ *
+ * @author Doug Simon
+ */
+public class LIRMonitorAddress extends LIRInstruction {
+
+    public final int monitor;
+
+    public LIRMonitorAddress(CiValue result, int monitor) {
+        super(LIROpcode.MonitorAddress, result, null, false);
+        this.monitor = monitor;
+    }
+
+    @Override
+    public void emitCode(LIRAssembler masm) {
+        masm.emitMonitorAddress(monitor, this.result());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRNegate.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2010, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.lir;
+
+import com.oracle.max.graal.compiler.globalstub.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code LIRNegate} class definition.
+ *
+ * @author Thomas Wuerthinger
+ *
+ */
+public class LIRNegate extends LIROp1 {
+
+    public GlobalStub globalStub;
+
+    /**
+     * Constructs a new instruction LIRNegate for a given operand.
+     *
+     * @param operand the input operand for this instruction
+     * @param result the result operand for this instruction
+     */
+    public LIRNegate(CiValue operand, CiValue result) {
+        super(LIROpcode.Neg, operand, result);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIROp0.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.lir;
+
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code LIROp0} class definition.
+ *
+ * @author Marcelo Cintra
+ *
+ */
+public class LIROp0 extends LIRInstruction {
+
+    /**
+     * Creates a LIROp0 instruction.
+     *
+     * @param opcode the opcode of the new instruction
+     */
+    public LIROp0(LIROpcode opcode) {
+        this(opcode, CiValue.IllegalValue);
+    }
+
+    /**
+     * Creates a LIROp0 instruction.
+     *
+     * @param opcode the opcode of the new instruction
+     * @param result the result operand to the new instruction
+     */
+    public LIROp0(LIROpcode opcode, CiValue result) {
+        this(opcode, result, null);
+    }
+
+    /**
+     * Creates a LIROp0 instruction.
+     *
+     * @param opcode the opcode of the new instruction
+     * @param result the result operand to the new instruction
+     * @param info used to emit debug information associated to this instruction
+     */
+    public LIROp0(LIROpcode opcode, CiValue result, LIRDebugInfo info) {
+        super(opcode, result, info, false);
+        assert isInRange(opcode, LIROpcode.BeginOp0, LIROpcode.EndOp0) : "Opcode " + opcode + " is invalid for a LIROP0 instruction";
+    }
+
+    /**
+     * Emit assembly code for this instruction.
+     * @param masm the target assembler
+     */
+    @Override
+    public void emitCode(LIRAssembler masm) {
+        masm.emitOp0(this);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIROp1.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.lir;
+
+import com.oracle.max.graal.compiler.util.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code LIROp1} class definition. The LIROp1 instruction has only one input operand.
+ *
+ * @author Marcelo Cintra
+ */
+public class LIROp1 extends LIRInstruction {
+
+    public enum LIRMoveKind {
+        Normal, Volatile, Unaligned
+    }
+
+    public final CiKind kind;          // the operand type
+    public final LIRMoveKind moveKind; // flag that indicate the kind of move
+
+    /**
+     * Constructs a new LIROp1 instruction.
+     *
+     * @param opcode the instruction's opcode
+     * @param opr the first input operand
+     * @param result the operand that holds the result of this instruction
+     * @param kind the kind of this instruction
+     * @param info the object holding information needed to emit debug information
+     */
+    public LIROp1(LIROpcode opcode, CiValue opr, CiValue result, CiKind kind, LIRDebugInfo info) {
+        super(opcode, result, info, false, 0, 0, opr);
+        this.kind = kind;
+        this.moveKind = LIRMoveKind.Normal;
+        assert isInRange(opcode, LIROpcode.BeginOp1, LIROpcode.EndOp1) : "The " + opcode + " is not a valid LIROp1 opcode";
+    }
+
+    /**
+     * Constructs a new LIROp1 instruction.
+     *
+     * @param opcode the instruction's opcode
+     * @param opr the first input operand
+     * @param result the operand that holds the result of this instruction
+     * @param kind the kind of this instruction
+     */
+    public LIROp1(LIROpcode opcode, CiValue opr, CiValue result, CiKind kind) {
+        this(opcode, opr, result, kind, null);
+    }
+
+    /**
+     * Constructs a new LIROp1 instruction.
+     *
+     * @param opcode the instruction's opcode
+     * @param opr the first input operand
+     * @param result the operand that holds the result of this instruction
+     */
+    public LIROp1(LIROpcode opcode, CiValue opr, CiValue result) {
+        this(opcode, opr, result, CiKind.Illegal);
+    }
+
+    /**
+     * Constructs a new LIROp1 instruction.
+     *
+     * @param opcode the instruction's opcode
+     * @param opr the first input operand
+     */
+    public LIROp1(LIROpcode opcode, CiValue opr) {
+        this(opcode, opr, CiValue.IllegalValue);
+    }
+
+    /**
+     * Constructs a new LIROp1 instruction.
+     *
+     * @param moveKind the kind of move the instruction represents
+     * @param operand the single input operand
+     * @param result the operand that holds the result of this instruction
+     * @param kind the kind of this instruction
+     * @param info the object holding information needed to emit debug information
+     */
+    public LIROp1(LIRMoveKind moveKind, CiValue operand, CiValue result, CiKind kind, LIRDebugInfo info) {
+        super(LIROpcode.Move, result, info, false, 0, 0, operand);
+        this.kind = kind;
+        this.moveKind = moveKind;
+    }
+
+    /**
+     * Constructs a new LIROp1 instruction.
+     *
+     * @param opcode the instruction's opcode
+     * @param opr the first input operand
+     * @param info the object holding information needed to emit debug information
+     */
+    public LIROp1(LIROpcode opcode, CiValue opr, LIRDebugInfo info) {
+        super(opcode, CiValue.IllegalValue, info, false, 0, 0, opr);
+        this.kind = CiKind.Illegal;
+        this.moveKind = LIRMoveKind.Normal;
+        assert isInRange(opcode, LIROpcode.BeginOp1, LIROpcode.EndOp1) : "The " + opcode + " is not a valid LIROp1 opcode";
+    }
+
+    /**
+     * Gets the input operand of this instruction.
+     *
+     * @return opr the input operand.
+     */
+    public CiValue operand() {
+        return operand(0);
+    }
+
+    /**
+     * Gets the kind of move of this instruction.
+     *
+     * @return flags the constant that represents the move kind.
+     */
+    public LIRMoveKind moveKind() {
+        assert code == LIROpcode.Move : "The opcode must be of type LIROpcode.Move in LIROp1";
+        return moveKind;
+    }
+
+    @Override
+    public void emitCode(LIRAssembler masm) {
+        masm.emitOp1(this);
+    }
+
+    @Override
+    public String name() {
+        if (code == LIROpcode.Move) {
+            switch (moveKind()) {
+                case Normal:
+                    return "move";
+                case Unaligned:
+                    return "unaligned move";
+                case Volatile:
+                    return "volatile_move";
+                default:
+                    throw Util.shouldNotReachHere();
+            }
+        } else {
+            return super.name();
+        }
+    }
+
+    @Override
+    public boolean verify() {
+        switch (code) {
+            case Move:
+                assert (operand().isLegal()) && (result().isLegal()) : "Operand and result must be valid in a LIROp1 move instruction.";
+                break;
+            case NullCheck:
+                assert operand().isVariableOrRegister() : "Operand must be a register in a LIROp1 null check instruction.";
+                break;
+            case Return:
+                assert operand().isVariableOrRegister() || operand().isIllegal() : "Operand must be (register | illegal) in a LIROp1 return instruction.";
+                break;
+        }
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIROp2.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.lir;
+
+import com.oracle.max.graal.compiler.ir.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code LIROp2} class represents a LIR instruction that performs an operation on two operands.
+ *
+ * @author Marcelo Cintra
+ * @author Thomas Wuerthinger
+ * @author Ben L. Titzer
+ */
+public class LIROp2 extends LIRInstruction {
+
+    final Condition condition;
+
+    /**
+     * Constructs a new LIROp2 instruction.
+     *
+     * @param opcode the instruction's opcode
+     * @param condition the instruction's condition
+     * @param opr1 the first input operand
+     * @param opr2 the second input operand
+     * @param info the object holding information needed to emit debug information
+     */
+    public LIROp2(LIROpcode opcode, Condition condition, CiValue opr1, CiValue opr2, LIRDebugInfo info) {
+        super(opcode, CiValue.IllegalValue, info, false, 0, 0, opr1, opr2);
+        this.condition = condition;
+        assert opcode == LIROpcode.Cmp : "Instruction opcode should be of type LIROpcode.Cmp";
+    }
+
+    /**
+     * Constructs a new LIROp2 instruction.
+     *
+     * @param opcode the instruction's opcode
+     * @param condition the instruction's condition
+     * @param opr1 the first input operand
+     * @param opr2 the second input operand
+     * @param result the operand that holds the result of this instruction
+     */
+    public LIROp2(LIROpcode opcode, Condition condition, CiValue opr1, CiValue opr2, CiValue result) {
+        super(opcode, result, null, false, 0, 0, opr1, opr2);
+        this.condition = condition;
+        assert opcode == LIROpcode.Cmove : "Instruction opcode should be of type LIROpcode.Cmove";
+    }
+
+    /**
+     * Constructs a new LIROp2 instruction.
+     *
+     * @param opcode the instruction's opcode
+     * @param opr1 the first input operand
+     * @param opr2 the second input operand
+     * @param result the operand that holds the result of this instruction
+     * @param info the object holding information needed to emit debug information
+     * @param kind the kind of this instruction
+     */
+    public LIROp2(LIROpcode opcode, CiValue opr1, CiValue opr2, CiValue result, LIRDebugInfo info, CiKind kind, boolean hasCall) {
+        super(opcode, result, info, hasCall, 0, 0, opr1, opr2);
+        this.condition = null;
+        assert opcode != LIROpcode.Cmp && isInRange(opcode, LIROpcode.BeginOp2, LIROpcode.EndOp2) : "The " + opcode + " is not a valid LIROp2 opcode";
+    }
+
+    /**
+     * Constructs a new LIROp2 instruction.
+     *
+     * @param opcode the instruction's opcode
+     * @param opr1 the instruction's first operand
+     * @param opr2 the instruction's second operand
+     * @param result the operand that holds the result of this instruction
+     * @param info the object holding information needed to emit debug information
+     */
+    public LIROp2(LIROpcode opcode, CiValue opr1, CiValue opr2, CiValue result, LIRDebugInfo info) {
+        this(opcode, opr1, opr2, result, info, CiKind.Illegal, false);
+    }
+
+    /**
+     * Constructs a new LIROp2 instruction.
+     *
+     * @param opcode the instruction's opcode
+     * @param opr1 the instruction's first operand
+     * @param opr2 the instruction's second operand
+     * @param result the operand that holds the result of this instruction
+     */
+    public LIROp2(LIROpcode opcode, CiValue opr1, CiValue opr2, CiValue result) {
+        this(opcode, opr1, opr2, result, (LIRDebugInfo) null);
+    }
+
+    /**
+     * Constructs a new LIROp2 instruction.
+     *
+     * @param opcode the instruction's opcode
+     * @param opr1 the first input operand
+     * @param opr2 the second input operand
+     * @param result the operand that holds the result of this instruction
+     * @param tmp the temporary operand used by this instruction
+     */
+    public LIROp2(LIROpcode opcode, CiValue opr1, CiValue opr2, CiValue result, CiValue tmp) {
+        super(opcode, result, null, false, 0, 1, opr1, opr2, tmp);
+        this.condition = null;
+        assert opcode != LIROpcode.Cmp && isInRange(opcode, LIROpcode.BeginOp2, LIROpcode.EndOp2) : "The " + opcode + " is not a valid LIROp2 opcode";
+    }
+
+    /**
+     * Gets the first input operand.
+     *
+     * @return opr1 the first input operand
+     */
+    public CiValue operand1() {
+        return operand(0);
+    }
+
+    /**
+     * Gets the second input operand.
+     *
+     * @return opr2 the second input operand
+     */
+    public CiValue operand2() {
+        return operand(1);
+    }
+
+    /**
+     * Gets the temporary operand of this instruction.
+     *
+     * @return tmp the temporary operand of this instruction
+     *
+     */
+    public CiValue tmp() {
+        return operand(2);
+    }
+
+    /**
+     * Gets the condition of this instruction, if it is a Cmp or Cmove LIR instruction.
+     *
+     * @return condition the condition of this instruction
+     */
+    public Condition condition() {
+        assert code == LIROpcode.Cmp || code == LIROpcode.Cmove : "Field access only valid for cmp and cmove";
+        return condition;
+    }
+
+    /**
+     * Emit target assembly code for this instruction.
+     *
+     * @param masm the target assembler
+     */
+    @Override
+    public void emitCode(LIRAssembler masm) {
+        masm.emitOp2(this);
+    }
+
+    /**
+     * Prints this instruction.
+     */
+    @Override
+    public String operationString(OperandFormatter operandFmt) {
+        if (code == LIROpcode.Cmove) {
+            return condition.toString() + " " + super.operationString(operandFmt);
+        }
+        return super.operationString(operandFmt);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIROp3.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.lir;
+
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code LIROp3} class definition.
+ *
+ * @author Marcelo Cintra
+ *
+ */
+public class LIROp3 extends LIRInstruction {
+
+    /**
+     * Creates a new LIROp3 instruction. A LIROp3 instruction represents a LIR instruction
+     * that has three input operands.
+     *
+     * @param opcode the instruction's opcode
+     * @param opr1 the first input operand
+     * @param opr2 the second input operand
+     * @param opr3 the third input operand
+     * @param result the result operand
+     * @param info the debug information, used for deoptimization, associated to this instruction
+     */
+    public LIROp3(LIROpcode opcode, CiValue opr1, CiValue opr2, CiValue opr3, CiValue result, LIRDebugInfo info) {
+        super(opcode, result, info, false, 1, 1, opr1, opr2, opr3);
+        assert isInRange(opcode, LIROpcode.BeginOp3, LIROpcode.EndOp3) : "The " + opcode + " is not a valid LIROp3 opcode";
+    }
+
+    /**
+     * Gets the opr1 of this class.
+     *
+     * @return the opr1
+     */
+    public CiValue opr1() {
+        return operand(0);
+    }
+
+    /**
+     * Gets the opr2 of this class.
+     *
+     * @return the opr2
+     */
+    public CiValue opr2() {
+        return operand(1);
+    }
+
+    /**
+     * Emits assembly code for this instruction.
+     *
+     * @param masm the target assembler
+     */
+    @Override
+    public void emitCode(LIRAssembler masm) {
+        masm.emitOp3(this);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIROpcode.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.lir;
+
+/**
+ * The {@code LirOpcode} enum represents the Operation code of each LIR instruction.
+ *
+ * @author Marcelo Cintra
+ * @author Thomas Wuerthinger
+ */
+public enum LIROpcode {
+    // Checkstyle: stop
+    // @formatter:off
+    BeginOp0,
+        Label,
+        Breakpoint,
+        RuntimeCall,
+        Membar,
+        Branch,
+        CondFloatBranch,
+    EndOp0,
+    BeginOp1,
+        NullCheck,
+        Return,
+        Lea,
+        Neg,
+        TableSwitch,
+        Move,
+        Prefetchr,
+        Prefetchw,
+        Convert,
+        Lsb,
+        Msb,
+        MonitorAddress,
+    EndOp1,
+    BeginOp2,
+        Cmp,
+        Cmpl2i,
+        Ucmpfd2i,
+        Cmpfd2i,
+        Cmove,
+        Add,
+        Sub,
+        Mul,
+        Div,
+        Rem,
+        Sqrt,
+        Abs,
+        Sin,
+        Cos,
+        Tan,
+        Log,
+        Log10,
+        LogicAnd,
+        LogicOr,
+        LogicXor,
+        Shl,
+        Shr,
+        Ushr,
+        CompareTo,
+    EndOp2,
+    BeginOp3,
+        Idiv,
+        Irem,
+        Ldiv,
+        Lrem,
+        Wdiv,
+        Wdivi,
+        Wrem,
+        Wremi,
+    EndOp3,
+    NativeCall,
+    DirectCall,
+    ConstDirectCall,
+    IndirectCall,
+    TemplateCall,
+    InstanceOf,
+    CheckCast,
+    StoreCheck,
+    CasLong,
+    CasWord,
+    CasObj,
+    CasInt,
+    Xir,
+    // @formatter:on
+    // Checkstyle: resume
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIROperand.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.lir;
+
+import com.sun.cri.ci.*;
+
+/**
+ * An instruction operand. If the register allocator can modify this operand (e.g. to replace a
+ * variable with a register), then it will have a corresponding entry in the {@link LIRInstruction#allocatorOperands}
+ * list of an instruction.
+ *
+ * @author Doug Simon
+ */
+public class LIROperand {
+
+    /**
+     * The value of the operand.
+     */
+    CiValue value;
+
+    LIROperand(CiValue value) {
+        this.value = value;
+    }
+
+    /**
+     * Gets the value of this operand. This may still be a {@linkplain CiVariable}
+     * if the register allocator has not yet assigned a register or stack address to the operand.
+     *
+     * @param inst the instruction containing this operand
+     */
+    public CiValue value(LIRInstruction inst) {
+        return value;
+    }
+
+    @Override
+    public String toString() {
+        return value.toString();
+    }
+
+    static class LIRVariableOperand extends LIROperand {
+        /**
+         * Index into an instruction's {@linkplain LIRInstruction#allocatorOperands allocator operands}.
+         */
+        final int index;
+
+        LIRVariableOperand(int index) {
+            super(null);
+            this.index = index;
+        }
+
+        @Override
+        public CiValue value(LIRInstruction inst) {
+            if (value == null) {
+                CiValue value = inst.allocatorOperands.get(index);
+                if (value.isVariable()) {
+                    return value;
+                }
+                this.value = value;
+            }
+            return value;
+        }
+
+        @Override
+        public String toString() {
+            if (value == null) {
+                return "operands[" + index + "]";
+            }
+            return value.toString();
+        }
+    }
+
+    /**
+     * An address operand with at least one {@linkplain CiVariable variable} constituent.
+     */
+    static class LIRAddressOperand extends LIROperand {
+        int base;
+        int index;
+
+        LIRAddressOperand(int base, int index, CiAddress address) {
+            super(address);
+            assert base != -1 || index != -1 : "address should have at least one variable part";
+            this.base = base;
+            this.index = index;
+        }
+
+        @Override
+        public CiValue value(LIRInstruction inst) {
+            if (base != -1 || index != -1) {
+                CiAddress address = (CiAddress) value;
+                CiValue baseOperand = base == -1 ? address.base : inst.allocatorOperands.get(base);
+                CiValue indexOperand = index == -1 ? address.index : inst.allocatorOperands.get(index);
+                if (address.index.isLegal()) {
+                    assert indexOperand.isVariableOrRegister();
+                    if (baseOperand.isVariable() || indexOperand.isVariable()) {
+                        return address;
+                    }
+                } else {
+                    if (baseOperand.isVariable()) {
+                        return address;
+                    }
+                }
+                value = new CiAddress(address.kind, baseOperand, indexOperand, address.scale, address.displacement);
+                base = -1;
+                index = -1;
+            }
+            return value;
+        }
+
+        @Override
+        public String toString() {
+            return value.toString();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRSignificantBit.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2010, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.lir;
+
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+/**
+ * LIR instruction used in translating {@link Bytecodes#LSB} and {@link Bytecodes#MSB}.
+ *
+ * @author Doug Simon
+ */
+public class LIRSignificantBit extends LIRInstruction {
+
+    public LIRSignificantBit(LIROpcode opcode, CiValue operand, CiValue result) {
+        super(opcode, result, null, false, 1, 0, operand);
+    }
+
+    @Override
+    public void emitCode(LIRAssembler masm) {
+        masm.emitSignificantBitOp(code == LIROpcode.Msb,  operand(0), result());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRTableSwitch.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.lir;
+
+import com.sun.cri.ci.*;
+
+/**
+ * @author Doug Simon
+ */
+public class LIRTableSwitch extends LIRInstruction {
+
+    public LIRBlock defaultTarget;
+
+    public final LIRBlock[] targets;
+
+    public final int lowKey;
+
+    public LIRTableSwitch(CiValue value, int lowKey, LIRBlock defaultTarget, LIRBlock[] targets) {
+        super(LIROpcode.TableSwitch, CiValue.IllegalValue, null, false, 1, 0, value);
+        this.lowKey = lowKey;
+        this.targets = targets;
+        this.defaultTarget = defaultTarget;
+    }
+
+    @Override
+    public void emitCode(LIRAssembler masm) {
+        masm.emitTableSwitch(this);
+    }
+
+    /**
+     * @return the input value to this switch
+     */
+    public CiValue value() {
+        return operand(0);
+    }
+
+    @Override
+    public String operationString(OperandFormatter operandFmt) {
+        StringBuilder buf = new StringBuilder(super.operationString(operandFmt));
+        buf.append("\ndefault: [B").append(defaultTarget.blockID()).append(']');
+        int key = lowKey;
+        for (LIRBlock b : targets) {
+            buf.append("\ncase ").append(key).append(": [B").append(b.blockID()).append(']');
+            key++;
+        }
+        return buf.toString();
+    }
+
+
+    private LIRBlock substitute(LIRBlock block, LIRBlock oldBlock, LIRBlock newBlock) {
+        if (block == oldBlock) {
+            LIRInstruction instr = newBlock.lir().instructionsList().get(0);
+            assert instr instanceof LIRLabel : "first instruction of block must be label";
+            return newBlock;
+        }
+        return oldBlock;
+    }
+
+    public void substitute(LIRBlock oldBlock, LIRBlock newBlock) {
+        if (substitute(defaultTarget, oldBlock, newBlock) == newBlock) {
+            defaultTarget = newBlock;
+        }
+        for (int i = 0; i < targets.length; i++) {
+            if (substitute(targets[i], oldBlock, newBlock) == newBlock) {
+                targets[i] = newBlock;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRXirInstruction.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.lir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+import com.sun.cri.xir.*;
+
+public class LIRXirInstruction extends LIRInstruction {
+
+    public final CiValue[] originalOperands;
+    public final int outputOperandIndex;
+    public final int[] operandIndices;
+    public final XirSnippet snippet;
+    public final RiMethod method;
+    public final int inputTempCount;
+    public final int tempCount;
+    public final int inputCount;
+    public final List<CiValue> pointerSlots;
+    public final LIRDebugInfo infoAfter;
+    private LIRBlock trueSuccessor;
+    private LIRBlock falseSuccessor;
+
+    public LIRXirInstruction(XirSnippet snippet,
+                             CiValue[] originalOperands,
+                             CiValue outputOperand,
+                             int inputTempCount,
+                             int tempCount,
+                             CiValue[] operands,
+                             int[] operandIndices,
+                             int outputOperandIndex,
+                             LIRDebugInfo info,
+                             LIRDebugInfo infoAfter,
+                             RiMethod method,
+                             List<CiValue> pointerSlots) {
+        super(LIROpcode.Xir, outputOperand, info, false, inputTempCount, tempCount, operands);
+        this.infoAfter = infoAfter;
+        this.pointerSlots = pointerSlots;
+        assert this.pointerSlots == null || this.pointerSlots.size() >= 0;
+        this.method = method;
+        this.snippet = snippet;
+        this.operandIndices = operandIndices;
+        this.outputOperandIndex = outputOperandIndex;
+        this.originalOperands = originalOperands;
+        this.inputTempCount = inputTempCount;
+        this.tempCount = tempCount;
+        this.inputCount = operands.length - inputTempCount - tempCount;
+
+        GraalMetrics.LIRXIRInstructions++;
+    }
+
+
+    public void setFalseSuccessor(LIRBlock falseSuccessor) {
+        this.falseSuccessor = falseSuccessor;
+    }
+
+
+    public void setTrueSuccessor(LIRBlock trueSuccessor) {
+        this.trueSuccessor = trueSuccessor;
+    }
+
+    public LIRBlock falseSuccessor() {
+        return falseSuccessor;
+    }
+
+    public LIRBlock trueSuccessor() {
+        return trueSuccessor;
+    }
+
+    public CiValue[] getOperands() {
+        for (int i = 0; i < operandIndices.length; i++) {
+            originalOperands[operandIndices[i]] = operand(i);
+        }
+        if (outputOperandIndex != -1) {
+            originalOperands[outputOperandIndex] = result();
+        }
+        return originalOperands;
+    }
+
+    /**
+     * Emits target assembly code for this instruction.
+     *
+     * @param masm the target assembler
+     */
+    @Override
+    public void emitCode(LIRAssembler masm) {
+        masm.emitXir(this);
+    }
+
+     /**
+     * Prints this instruction.
+     */
+    @Override
+    public String operationString(OperandFormatter operandFmt) {
+        return toString(operandFmt);
+    }
+
+    @Override
+    public String toString(OperandFormatter operandFmt) {
+        StringBuilder sb = new StringBuilder();
+        sb.append("XIR: ");
+
+        if (result().isLegal()) {
+            sb.append(operandFmt.format(result()) + " = ");
+        }
+
+        sb.append(snippet.template);
+        sb.append("(");
+        for (int i = 0; i < snippet.arguments.length; i++) {
+            XirArgument a = snippet.arguments[i];
+            if (i > 0) {
+                sb.append(", ");
+            }
+            if (a.constant != null) {
+                sb.append(operandFmt.format(a.constant));
+            } else {
+                Object o = a.object;
+                if (o instanceof LIRItem) {
+                    sb.append(operandFmt.format(((LIRItem) o).result()));
+                } else if (o instanceof CiValue) {
+                    sb.append(operandFmt.format((CiValue) o));
+                } else {
+                    sb.append(o);
+                }
+            }
+        }
+        sb.append(')');
+
+        if (method != null) {
+            sb.append(" method=");
+            sb.append(method.toString());
+        }
+
+
+        for (LIRInstruction.OperandMode mode : LIRInstruction.OPERAND_MODES) {
+            int n = operandCount(mode);
+            if (mode == OperandMode.Output && n <= 1) {
+                // Already printed single output (i.e. result())
+                continue;
+            }
+            if (n != 0) {
+                sb.append(' ').append(mode.name().toLowerCase()).append("=(");
+                HashSet<String> operands = new HashSet<String>();
+                for (int i = 0; i < n; i++) {
+                    String operand = operandFmt.format(operandAt(mode, i));
+                    if (!operands.contains(operand)) {
+                        if (!operands.isEmpty()) {
+                            sb.append(", ");
+                        }
+                        operands.add(operand);
+                        sb.append(operand);
+                    }
+                }
+                sb.append(')');
+            }
+        }
+
+        appendDebugInfo(sb, operandFmt, info);
+
+        return sb.toString();
+    }
+
+
+    public void substitute(LIRBlock block, LIRBlock newTarget) {
+        if (trueSuccessor == block) {
+            trueSuccessor = newTarget;
+        }
+
+        if (falseSuccessor == block) {
+            falseSuccessor = newTarget;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/package-info.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @author Marcelo Cintra
+ * @author Thomas Wuerthinger
+ *
+ * Port of the backend (LIR) of the client compiler to Java.
+ */
+package com.oracle.max.graal.compiler.lir;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/observer/CompilationEvent.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,166 @@
+/*
+ * 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.max.graal.compiler.observer;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.alloc.*;
+import com.oracle.max.graal.compiler.graph.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * An event that occurred during compilation. Instances of this class provide information about the event and the state
+ * of the compilation when the event was raised. {@link #getCompilation()} and {@link #getMethod()} are guaranteed to
+ * always return a non-{@code null} value. Other objects provided by getter methods may be {@code null},
+ * depending on the available information when and where the event was triggered.
+ *
+ * @author Peter Hofer
+ */
+public class CompilationEvent {
+
+    private final GraalCompilation compilation;
+    private final String label;
+    private Graph graph;
+
+    private BlockMap blockMap;
+    private int codeSize = -1;
+
+    private LinearScan allocator;
+    private CiTargetMethod targetMethod;
+    private boolean hirValid = false;
+    private boolean lirValid = false;
+    private boolean errorEvent;
+    private Map<String, Object> debugObjects;
+
+    private Interval[] intervals;
+    private int intervalsSize;
+    private Interval[] intervalsCopy = null;
+
+    public CompilationEvent(GraalCompilation compilation) {
+        this(compilation, null);
+    }
+
+    private CompilationEvent(GraalCompilation compilation, String label) {
+        assert compilation != null;
+        this.label = label;
+        this.compilation = compilation;
+    }
+
+    public CompilationEvent(GraalCompilation compilation, String label, Graph graph, boolean hirValid, boolean lirValid) {
+        this(compilation, label, graph, hirValid, lirValid, false, (Map<String, Object>) null);
+    }
+    public CompilationEvent(GraalCompilation compilation, String label, Graph graph, boolean hirValid, boolean lirValid, boolean error) {
+        this(compilation, label, graph, hirValid, lirValid, error, (Map<String, Object>) null);
+    }
+
+    public CompilationEvent(GraalCompilation compilation, String label, Graph graph, boolean hirValid, boolean lirValid, Map<String, Object> debugObjects) {
+        this(compilation, label, graph, hirValid, lirValid, false, debugObjects);
+    }
+
+    public CompilationEvent(GraalCompilation compilation, String label, Graph graph, boolean hirValid, boolean lirValid, boolean error, Map<String, Object> debugObjects) {
+        this(compilation, label);
+        this.graph = graph;
+        this.hirValid = hirValid;
+        this.lirValid = lirValid;
+        this.debugObjects = debugObjects;
+        this.errorEvent = error;
+    }
+
+    public CompilationEvent(GraalCompilation compilation, String label, Graph graph, boolean hirValid, boolean lirValid, CiTargetMethod targetMethod) {
+        this(compilation, label, graph, hirValid, lirValid);
+        this.targetMethod = targetMethod;
+    }
+
+    public CompilationEvent(GraalCompilation compilation, String label, BlockMap blockMap, int codeSize) {
+        this(compilation, label);
+        this.blockMap = blockMap;
+        this.codeSize = codeSize;
+    }
+
+    public CompilationEvent(GraalCompilation compilation, String label, LinearScan allocator, Interval[] intervals, int intervalsSize) {
+        this(compilation, label);
+        this.allocator = allocator;
+        this.intervals = intervals;
+        this.intervalsSize = intervalsSize;
+    }
+
+    public GraalCompilation getCompilation() {
+        return compilation;
+    }
+
+    public String getLabel() {
+        return label;
+    }
+
+    public RiMethod getMethod() {
+        return compilation.method;
+    }
+
+    public BlockMap getBlockMap() {
+        return blockMap;
+    }
+
+    public Graph getGraph() {
+        return graph;
+    }
+
+    public LinearScan getAllocator() {
+        return allocator;
+    }
+
+    public CiTargetMethod getTargetMethod() {
+        return targetMethod;
+    }
+
+    public boolean isHIRValid() {
+        return hirValid;
+    }
+
+    public boolean isLIRValid() {
+        return lirValid;
+    }
+
+    public boolean isErrorEvent() {
+        return errorEvent;
+    }
+
+    public Interval[] getIntervals() {
+        if (intervalsCopy == null && intervals != null) {
+            // deferred copy of the valid range of the intervals array
+            intervalsCopy = Arrays.copyOf(intervals, intervalsSize);
+        }
+        return intervalsCopy;
+    }
+
+    public int getCodeSize() {
+        return codeSize;
+    }
+
+
+    public Map<String, Object> getDebugObjects() {
+        return debugObjects;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/observer/CompilationObserver.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,57 @@
+/*
+ * 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.max.graal.compiler.observer;
+
+import com.oracle.max.graal.compiler.*;
+
+/**
+ * Interface for classes that observe events of an {@link ObservableCompiler}.
+ *
+ * @author Peter Hofer
+ */
+public interface CompilationObserver {
+
+    /**
+     * Called when compilation of a method has started. This is always the first event raised for a particular
+     * {@link GraalCompilation}.
+     *
+     * @param event Information associated with the event and current state of the compilation.
+     */
+    void compilationStarted(CompilationEvent event);
+
+    /**
+     * Called when an event has occurred, for example that a particular phase in the compilation has been entered.
+     *
+     * @param event Information associated with the event and current state of the compilation.
+     */
+    void compilationEvent(CompilationEvent event);
+
+    /**
+     * Called when compilation of a method has completed (successfully or not). This is always the last event raised for
+     * a particular {@link GraalCompilation}.
+     *
+     * @param event Information associated with the event and current state of the compilation.
+     */
+    void compilationFinished(CompilationEvent event);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/observer/ObservableCompiler.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,99 @@
+/*
+ * 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.max.graal.compiler.observer;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.debug.*;
+
+/**
+ * Base class for compilers that notify subscribed {@link CompilationObserver CompilationObservers} of
+ * {@link CompilationEvent CompilationEvents} that occur during their compilations.
+ *
+ * @author Peter Hofer
+ */
+public class ObservableCompiler {
+
+    private List<CompilationObserver> observers;
+
+    /**
+     * @return {@code true} if one or more observers are subscribed to receive notifications from this compiler,
+     *         {@code false} otherwise.
+     */
+    public boolean isObserved() {
+        return observers != null && !TTY.isSuppressed();
+    }
+
+    /**
+     * Add the specified observer to receive events from this compiler.
+     *
+     * @param observer The observer to add.
+     */
+    public void addCompilationObserver(CompilationObserver observer) {
+        assert observer != null;
+
+        if (observers == null) {
+            observers = new LinkedList<CompilationObserver>();
+        }
+        observers.add(observer);
+    }
+
+    public void fireCompilationStarted(CompilationEvent event) {
+        if (isObserved()) {
+            for (CompilationObserver observer : observers) {
+                observer.compilationStarted(event);
+            }
+        }
+    }
+
+    public void fireCompilationEvent(CompilationEvent event) {
+        if (isObserved()) {
+            for (CompilationObserver observer : observers) {
+                observer.compilationEvent(event);
+            }
+        }
+    }
+
+    public void fireCompilationFinished(CompilationEvent event) {
+        if (isObserved()) {
+            for (CompilationObserver observer : observers) {
+                observer.compilationFinished(event);
+            }
+        }
+    }
+
+    /**
+     * Remove the specified observer so that it no longer receives events from this compiler.
+     *
+     * @param observer The observer to remove.
+     */
+    public void removeCompilationObserver(CompilationObserver observer) {
+        if (observers != null) {
+            observers.remove(observer);
+            if (observers.size() == 0) {
+                observers = null;
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/observer/package-info.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+/**
+ * Classes and interfaces for observing compilations.
+ *
+ * @author Peter Hofer
+ */
+package com.oracle.max.graal.compiler.observer;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/package-info.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+/**
+ * The top-level package in Graal containing options, metrics, timers and the main compiler class
+ * {@link com.oracle.max.graal.compiler.GraalCompiler}.
+ *
+ * <H2>{@code GraalCompiler} Overview</H2>
+ *
+ * Graal is intended to be used with multiple JVM's so makes no use of or reference to classes for a specific JVM, for
+ * example Maxine.
+ *
+ * The compiler is represented by the class {@code GraalCompiler}. {@code GraalCompiler} binds a specific target
+ * architecture and JVM interface to produce a usable compiler object. There are
+ * two variants of {@code compileMethod}, one of which is used when doing <i>on stack replacement</i> (OSR), discussed
+ * later. The main variant takes {@link com.sun.cri.ri.RiMethod} and {@link com.sun.cri.xir.RiXirGenerator} arguments.
+ * {@code RiMethod} is Graal's representation of a Java method and {@code RiXirGenerator} represents the interface through
+ * which the compiler requests the XIR for a given bytecode from the runtime system.
+ *
+ * <H3>The Graal Compilation Process</H3>
+ *
+ * {@link com.oracle.max.graal.compiler.GraalCompiler#compileMethod} creates a {@link GraalCompilation} instance and then returns the result of calling its
+ * {@link com.oracle.max.graal.compiler.GraalCompilation#compile} method. The {@code GraalCompilation} instance records whether {@code compileMethod} was invoked with
+ * the OSR variant, which is used later in the IR generation.
+ * <p>
+ * While there is only one {@code GraalCompiler} instance, there may be several compilations proceeding concurrently, each of
+ * which is represented by a unique {@code GraalCompilation} instance. The static method {@link com.oracle.max.graal.compiler.GraalCompilation#current}} returns the
+ * {@code GraalCompilation} instance associated with the current thread, and is managed using a {@link java.lang.ThreadLocal} variable. It
+ * is used when assigning the unique id that is used for tracing  output to an HIR node. Each {@code GraalCompilation} instance
+ * has an associated {@link com.sun.cri.ci.CiStatistics} object that accumulates information about the compilation process, but is also
+ * used as a generator of, for example, basic block identifiers.
+ * <p>
+ * The compilation begins by calling {@link com.oracle.max.graal.compiler.GraalCompilation#emitHIR}, which creates the high-level intermediate representation (HIR) from the
+ * bytecodes of the method. The HIR is managed by the {@link com.oracle.max.graal.compiler.graph.IR} class, an instance of which is created by
+ * {@code emitHR}, which then calls the {{@link com.oracle.max.graal.compiler.graph.IR#build}} method and returns the result. The {@code GraalCompilation} and {@code IR}
+ * instances are are bi-directionally linked.
+ *
+ * <H3>Supported backends</H3>
+ *
+ * <ul>
+ * <li>AMD64/x64 with SSE2</li>
+ * </ul>
+ *
+ * <H2>Notes and Todos</H2> This is a collection of notes about the Graal compiler, including future directions,
+ * refactorings, missing features, broken features, etc.
+ *
+ *
+ * <h3>Anticipated Refactorings</h3>
+ *
+ * <ul>
+ * <li>
+ * The HIR nodes {@link com.oracle.max.graal.compiler.ir.UnsafePrefetch}, {@link com.oracle.max.graal.compiler.ir.UnsafePutObject}, etc should be replaced by uses of the newer
+ * {@link com.oracle.max.graal.compiler.ir.LoadPointer} and {@link com.oracle.max.graal.compiler.ir.StorePointer} nodes. Currently, the unsafe nodes are only generated by
+ * the creation of an OSR entry. Benefit: reduce the number of different IR nodes.</li>
+ *
+ * <li>
+ * Add a field to optionally store an {@link com.oracle.max.graal.compiler.ir.Info} object for each HIR node, and remove the
+ * {@link com.oracle.max.graal.compiler.ir.FixedNodeWithNext#exceptionHandlers} field, the {@link com.oracle.max.graal.compiler.ir.FixedNodeWithNext#bci} field, and any fields to store the Java
+ * frame state in subclasses. Benefit: saves space if most HIR nodes do not have exception handlers, a bci or Java frame
+ * state. Removes virtual dispatch on accessing debug information for nodes. Allows any node, regardless of its type, to
+ * have info attached.</li>
+ *
+ * <li>
+ * Migrate all HIR nodes to use the immutable {@link com.oracle.max.graal.compiler.value.FrameStateInfo} for debugging information. The {@link com.oracle.max.graal.compiler.value.FrameState}
+ * class is mutable and used throughout graph building. Benefit: {@code FrameStateInfo} would save both total space in
+ * the IR graph prevent many bugs due to the mutability of {@code FrameState}.</li>
+ *
+ * <li>
+ * Move the {@code FrameState} class to an inner class, or combine entirely, with the {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase} class. After
+ * the introduction of the {@code FrameStateInfo} into HIR nodes, the mutable value stack should only need to be
+ * accessed from the graph builder.</li>
+ *
+ * </ul>
+ *
+ * <h3>Missing or incomplete features</h3>
+ *
+ * There are some features of C1 that were not ported forward or finished given the time constraints for the Graal port. A
+ * list appears below.
+ *
+ * <ul>
+ * <li>
+ * Deoptimization metadata. The locations of all local variables and stack values are not communicated back to the
+ * runtime system through the {@link com.sun.cri.ci.CiDebugInfo} class yet. Such values are known to the register allocator, and there
+ * vestigial logic to compute them still there in the
+ * {@link com.oracle.max.graal.compiler.alloc.LinearScan#computeDebugInfo} method. To complete this metadata, the
+ * {@link com.oracle.max.graal.compiler.alloc.LinearScan} class must implement the {@link ValueLocator} interface and pass it to the
+ * {@link com.oracle.max.graal.compiler.lir.LIRDebugInfo#createFrame} method after register allocation. The
+ * resulting debug info will be fed back to the runtime system by the existing logic that calls
+ * {@link com.sun.cri.ci.CiTargetMethod#recordCall(int, Object, CiDebugInfo, boolean)} and other methods. Obviously the runtime
+ * system will need to encode this metadata in a dense format, because it is huge.</li>
+ *
+ *
+ * <li>
+ * Tiered compilation support. C1 supported the ability to add instrumentation to branches, invocations, and checkcasts
+ * in order to feed profile information to the C2 compiler in a tiered compilation setup. It relied on adding some
+ * information to the HIR nodes that represent these operations ({@link Invoke}, {@link CheckCast}, etc). All of this
+ * logic was removed to simplify both the front end and back end in anticipation of designing a future instrumentation
+ * API. XIR should be general enough to allow instrumentation code to be added to invocation and checkcast sites, but
+ * currently has no support for adding code at branches.
+ *
+ * </li>
+ *
+  * <li>
+ * SPARC and other architecture support. There pretty well-delineated separation between the architecture-independent
+ * part of LIR backend and the architecture-dependent, but the only implementation that current exists is the X86
+ * backend ({@link com.oracle.max.graal.compiler.target.amd64.AMD64Backend}, {@link com.oracle.max.graal.compiler.target.amd64.AMD64LIRGenerator}, {@link com.oracle.max.graal.compiler.target.amd64.AMD64LIRAssembler}, etc).</li>
+ *
+ * <li>
+ * XIR for safepoints. The Graal backend should use XIR to get the code for safepoints, but currently it still uses the
+ * handwritten logic (currently only compatible with Maxine).</li>
+ *
+ * </ul>
+ *
+ * <h3>Untested features</h3>
+ *
+ * <ul>
+ *
+ * <li>
+ * Reference map for outgoing overflow arguments. If a Graal method calls another method that has overflow arguments, it
+ * is not clear if the outgoing overflow argument area, which may contain references, has the appropriate bits set in
+ * the reference map for the Graal method's frame. Such arguments may be live in the called method.</li>
+ *
+ * <li>
+ * Although it should work, inlining synchronized methods or methods with exception handlers hasn't been tested.</li>
+ * <li>
+ * On-stack replacement. Graal retains all of the special logic for performing an OSR compilation. This is basically a
+ * compilation with a second entrypoint for entry from the interpreter. However, the generation of a runtime-specific
+ * entry sequence was never tested.</li>
+ *
+ * <li>
+ * {@link com.oracle.max.graal.compiler.GraalIntrinsic Intrinsification} is the mechanism by which the compiler recognizes calls to special JDK or
+ * runtime methods and replaces them with custom code. It is enabled by the {@link com.oracle.max.graal.compiler.GraalOptions#OptIntrinsify} compiler
+ * option. The Graal backend has never been tested with intrinsified arithmetic or floating point operations. For best
+ * performance, it should generate specialized machine code for arithmetic and floating point, perhaps using global
+ * stubs for complex floating point operations. <br>
+ * <i>Note</i>: Folding of special intrinsified methods is supported, tested, and working. The runtime system may
+ * register methods to be folded by using the
+ * {@link com.oracle.max.graal.compiler.GraalIntrinsic#registerFoldableMethod(RiMethod, java.lang.reflect.Method)} call. When the compiler encounters a
+ * call to such a registered method where the parameters are all constants, it invokes the supplied method with
+ * reflection. If the reflective call produces a value and does not throw an exception, Graal replaces the call to the
+ * method with the result.</li>
+ * </ul>
+ *
+ * <h3>Broken features</h3>
+ *
+ * <ul>
+ * <li>
+ * {@link com.oracle.max.graal.compiler.opt.LoopPeeler Loop peeling} was written by Marcelo Cintra near the end of his internship. It was never completed
+ * and should be considered broken. It only remains as a sketch of how loop peeling would be implemented in Graal, or in
+ * case he would finish the implementation and test it.</li>
+ *
+ * <li>
+ * Calls to global stubs should allocate space on the caller's stack. On AMD64 currently, calls to global stubs poke the
+ * arguments onto the stack below the RSP (i.e. in the callee's stack). While normally this code sequence is
+ * uninterruptible and works fine in the VM, signal handlers triggered when debugging or inspecting this code sequence
+ * may destroy these values when the OS calls the signal handler. This requires knowing which global stubs are called
+ * before finalizing the frame size; currently only the calls to
+ * {@link com.oracle.max.graal.compiler.target.amd64.AMD64MacroAssembler#callRuntimeCalleeSaved}
+ * do not fit this pattern. This needs to be fixed so that all global stubs that are called by the assembled code are
+ * known before beginning assembling. The {@link com.oracle.max.graal.compiler.target.amd64.AMD64GlobalStubEmitter} controls how the global stubs accept their
+ * parameters. See {@link com.oracle.max.graal.compiler.target.amd64.AMD64GlobalStubEmitter#callerFrameContainsArguments} and its usages.
+ *
+ * </li>
+ * </ul>
+ */
+package com.oracle.max.graal.compiler;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/CanonicalizerPhase.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,64 @@
+/*
+ * 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.max.graal.compiler.phases;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.graph.*;
+
+public class CanonicalizerPhase extends Phase {
+    private static final int MAX_ITERATION_PER_NODE = 10;
+
+    private boolean newNodes;
+
+    public CanonicalizerPhase() {
+        this(false);
+    }
+
+    public CanonicalizerPhase(boolean newNodes) {
+        this.newNodes = newNodes;
+    }
+
+    @Override
+    protected void run(Graph graph) {
+        NodeWorkList nodeWorkList = graph.createNodeWorkList(!newNodes, MAX_ITERATION_PER_NODE);
+        if (newNodes) {
+            nodeWorkList.addAll(graph.getNewNodes());
+        }
+        for (Node node : nodeWorkList) {
+            CanonicalizerOp op = node.lookup(CanonicalizerOp.class);
+            if (op != null) {
+                Node canonical = op.canonical(node);
+                if (canonical != node) {
+                    node.replaceAndDelete(canonical);
+                    nodeWorkList.replaced(canonical, node, true, EdgeType.USAGES);
+                    //System.out.println("-->" + n + " canonicalized to " + canonical);
+                    GraalMetrics.NodesCanonicalized++;
+                }
+            }
+        }
+    }
+
+    public interface CanonicalizerOp extends Op {
+        Node canonical(Node node);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/ComputeProbabilityPhase.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,294 @@
+/*
+ * 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.max.graal.compiler.phases;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.graph.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.observer.*;
+import com.oracle.max.graal.graph.*;
+
+public class ComputeProbabilityPhase extends Phase {
+    private static final double EPSILON = 1d / Integer.MAX_VALUE;
+
+    /*
+     * The computation of absolute probabilities works in three steps:
+     *
+     * - The first step, "PropagateProbability", traverses the graph in post order (merges after their ends, ...) and keeps track of the "probability state".
+     *   Whenever it encounters a ControlSplit it uses the splits probability information to divide the probability upon the successors.
+     *   Whenever it encounters an Invoke it assumes that the exception edge is unlikely and propagates the whole probability to the normal successor.
+     *   Whenever it encounters a Merge it sums up the probability of all predecessors.
+     *   It also maintains a set of active loops (whose LoopBegin has been visited) and builds def/use information for the second step.
+     *
+     * - The third step propagates the loop frequencies and multiplies each FixedNode's probability with its loop frequency.
+     *
+     *   TODO: add exception probability information to Invokes
+     */
+
+    @Override
+    protected void run(Graph graph) {
+        new PropagateProbability((FixedNode) graph.start().next()).apply();
+        GraalCompilation compilation = GraalCompilation.compilation();
+        if (compilation.compiler.isObserved() && GraalOptions.TraceProbability) {
+            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After PropagateProbability", graph, true, false));
+        }
+        computeLoopFactors();
+        if (compilation.compiler.isObserved() && GraalOptions.TraceProbability) {
+            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After computeLoopFactors", graph, true, false));
+        }
+        new PropagateLoopFrequency((FixedNode) graph.start().next()).apply();
+    }
+
+    private void computeLoopFactors() {
+        if (GraalOptions.TraceProbability) {
+            for (LoopInfo info : loopInfos) {
+                TTY.println("\nLoop " + info.loopBegin);
+                TTY.print("  requires: ");
+                for (LoopInfo r : info.requires) {
+                    TTY.print(r.loopBegin + " ");
+                }
+                TTY.println();
+            }
+        }
+        for (LoopInfo info : loopInfos) {
+            double frequency = info.loopFrequency();
+            assert frequency != -1;
+        }
+    }
+
+    private static boolean isRelativeProbability(double prob) {
+        // 1.01 to allow for some rounding errors
+        return prob >= 0 && prob <= 1.01;
+    }
+
+    public static class LoopInfo {
+        public final LoopBegin loopBegin;
+
+        public final Set<LoopInfo> requires = new HashSet<LoopInfo>(4);
+
+        private double loopFrequency = -1;
+        public boolean ended = false;
+
+        public LoopInfo(LoopBegin loopBegin) {
+            this.loopBegin = loopBegin;
+        }
+
+        public double loopFrequency() {
+            if (loopFrequency == -1 && ended) {
+                double factor = 1;
+                for (LoopInfo required : requires) {
+                    double t = required.loopFrequency();
+                    if (t == -1) {
+                        return -1;
+                    }
+                    factor *= t;
+                }
+                double d = loopBegin.loopEnd().probability() * factor;
+                if (d < EPSILON) {
+                    d = EPSILON;
+                } else if (d > loopBegin.probability() - EPSILON) {
+                    d = loopBegin.probability() - EPSILON;
+                }
+                loopFrequency = loopBegin.probability() / (loopBegin.probability() - d);
+                loopBegin.setLoopFrequency(loopFrequency);
+//                TTY.println("computed loop Frequency %f for %s", loopFrequency, loopBegin);
+            }
+            return loopFrequency;
+        }
+    }
+
+    public Set<LoopInfo> loopInfos = new HashSet<LoopInfo>();
+    public Map<Merge, Set<LoopInfo>> mergeLoops = new HashMap<Merge, Set<LoopInfo>>();
+
+    private class Probability implements MergeableState<Probability> {
+        public double probability;
+        public HashSet<LoopInfo> loops;
+        public LoopInfo loopInfo;
+
+        public Probability(double probability, HashSet<LoopInfo> loops) {
+            this.probability = probability;
+            this.loops = new HashSet<LoopInfo>(4);
+            if (loops != null) {
+                this.loops.addAll(loops);
+            }
+        }
+
+        @Override
+        public Probability clone() {
+            return new Probability(probability, loops);
+        }
+
+        @Override
+        public boolean merge(Merge merge, Collection<Probability> withStates) {
+            if (merge.endCount() > 1) {
+                HashSet<LoopInfo> intersection = new HashSet<LoopInfo>(loops);
+                for (Probability other : withStates) {
+                    intersection.retainAll(other.loops);
+                }
+                for (LoopInfo info : loops) {
+                    if (!intersection.contains(info)) {
+    //                    TTY.println("probability for %s at %s", info.loopBegin, merge);
+                        double loopFrequency = info.loopFrequency();
+                        if (loopFrequency == -1) {
+    //                        TTY.println("re-queued " + merge);
+                            return false;
+                        }
+                        probability *= loopFrequency;
+                    }
+                }
+                for (Probability other : withStates) {
+                    double prob = other.probability;
+                    for (LoopInfo info : other.loops) {
+                        if (!intersection.contains(info)) {
+    //                        TTY.println("probability for %s at %s", info.loopBegin, merge);
+                            double loopFrequency = info.loopFrequency();
+                            if (loopFrequency == -1) {
+    //                            TTY.println("re-queued " + merge);
+                                return false;
+                            }
+                            prob *= loopFrequency;
+                        }
+                    }
+                    probability += prob;
+                }
+                loops = intersection;
+    //            TTY.println("merged " + merge);
+                mergeLoops.put(merge, new HashSet<LoopInfo>(intersection));
+                assert isRelativeProbability(probability) : probability;
+            }
+            return true;
+        }
+
+        @Override
+        public void loopBegin(LoopBegin loopBegin) {
+            loopInfo = new LoopInfo(loopBegin);
+            loopInfos.add(loopInfo);
+            loops.add(loopInfo);
+        }
+
+        @Override
+        public void loopEnd(LoopEnd loopEnd, Probability loopEndState) {
+            assert loopInfo != null;
+            for (LoopInfo innerLoop : loopEndState.loops) {
+                if (innerLoop != loopInfo && !loops.contains(innerLoop)) {
+                    loopInfo.requires.add(innerLoop);
+                }
+            }
+            loopInfo.ended = true;
+        }
+
+        @Override
+        public void afterSplit(FixedNode node) {
+            assert node.predecessors().size() == 1;
+            Node pred = node.predecessors().get(0);
+            if (pred instanceof Invoke) {
+                Invoke x = (Invoke) pred;
+                if (x.next() != node) {
+                    probability = 0;
+                }
+            } else {
+                assert pred instanceof ControlSplit;
+                ControlSplit x = (ControlSplit) pred;
+                double sum = 0;
+                for (int i = 0; i < x.blockSuccessorCount(); i++) {
+                    if (x.blockSuccessor(i) == node) {
+                        sum += x.probability(i);
+                    }
+                }
+                probability *= sum;
+            }
+        }
+    }
+
+    private class PropagateProbability extends PostOrderNodeIterator<Probability> {
+
+        public PropagateProbability(FixedNode start) {
+            super(start, new Probability(1d, null));
+        }
+
+        @Override
+        protected void node(FixedNode node) {
+//            TTY.println(" -- %7.5f %s", state.probability, node);
+            node.setProbability(state.probability);
+        }
+    }
+
+    private class LoopCount implements MergeableState<LoopCount> {
+        public double count;
+
+        public LoopCount(double count) {
+            this.count = count;
+        }
+
+        @Override
+        public LoopCount clone() {
+            return new LoopCount(count);
+        }
+
+        @Override
+        public boolean merge(Merge merge, Collection<LoopCount> withStates) {
+            assert merge.endCount() == withStates.size() + 1;
+            if (merge.endCount() > 1) {
+                Set<LoopInfo> loops = mergeLoops.get(merge);
+//                TTY.println("merging count for %s: %d ends, %d loops", merge, merge.endCount(), loops.size());
+                assert loops != null;
+                double countProd = 1;
+                for (LoopInfo loop : loops) {
+                    countProd *= loop.loopFrequency();
+                }
+                count = countProd;
+            }
+            return true;
+        }
+
+        @Override
+        public void loopBegin(LoopBegin loopBegin) {
+            count *= loopBegin.loopFrequency();
+        }
+
+        @Override
+        public void loopEnd(LoopEnd loopEnd, LoopCount loopEndState) {
+            // nothing to do...
+        }
+
+        @Override
+        public void afterSplit(FixedNode node) {
+            // nothing to do...
+        }
+    }
+
+    private class PropagateLoopFrequency extends PostOrderNodeIterator<LoopCount> {
+
+        public PropagateLoopFrequency(FixedNode start) {
+            super(start, new LoopCount(1d));
+        }
+
+        @Override
+        protected void node(FixedNode node) {
+            node.setProbability(node.probability() * state.count);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.phases;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.graph.*;
+
+
+public class DeadCodeEliminationPhase extends Phase {
+
+    private NodeFlood flood;
+    private Graph graph;
+
+    @Override
+    protected void run(Graph graph) {
+        this.graph = graph;
+        this.flood = graph.createNodeFlood();
+
+        flood.add(graph.start());
+        iterateSuccessors();
+        disconnectCFGNodes();
+        iterateInputs();
+        disconnectNodes();
+        deleteNodes();
+
+        // remove chained Merges
+        for (Merge merge : graph.getNodes(Merge.class)) {
+            if (merge.endCount() == 1 && !(merge instanceof LoopBegin)) {
+                replacePhis(merge);
+                EndNode endNode = merge.endAt(0);
+                FixedNode next = merge.next();
+                merge.delete();
+                endNode.replaceAndDelete(next);
+            }
+        }
+
+        new PhiSimplifier(graph);
+    }
+
+    private void iterateSuccessors() {
+        for (Node current : flood) {
+            if (current instanceof EndNode) {
+                EndNode end = (EndNode) current;
+                flood.add(end.merge());
+            } else {
+                for (Node successor : current.successors()) {
+                    flood.add(successor);
+                }
+            }
+
+            if (current instanceof AbstractVectorNode) {
+                for (Node usage : current.usages()) {
+                    flood.add(usage);
+                }
+            }
+        }
+    }
+
+    private void disconnectCFGNodes() {
+        for (Node node : graph.getNodes()) {
+            if (!flood.isMarked(node)) {
+                if (node instanceof EndNode) {
+                    EndNode end = (EndNode) node;
+                    Merge merge = end.merge();
+                    if (merge != null && flood.isMarked(merge)) {
+                        // We are a dead end node leading to a live merge.
+                        merge.removeEnd(end);
+                    }
+                } else if (node instanceof LoopEnd) {
+                    LoopBegin loop = ((LoopEnd) node).loopBegin();
+                    if (flood.isMarked(loop)) {
+                        if (GraalOptions.TraceDeadCodeElimination) {
+                            TTY.println("Building loop begin node back: " + loop);
+                        }
+                        ((LoopEnd) node).setLoopBegin(null);
+                        EndNode endNode = loop.endAt(0);
+                        assert endNode.predecessors().size() == 1 : endNode.predecessors().size();
+                        replacePhis(loop);
+                        endNode.replaceAndDelete(loop.next());
+                        loop.delete();
+                    }
+                }
+            }
+        }
+    }
+
+    private void replacePhis(Merge merge) {
+        for (Node usage : new ArrayList<Node>(merge.usages())) {
+            assert usage instanceof Phi;
+            usage.replaceAndDelete(((Phi) usage).valueAt(0));
+        }
+    }
+
+    private void deleteNodes() {
+        for (Node node : graph.getNodes()) {
+            if (!flood.isMarked(node)) {
+                for (int i = 0; i < node.inputs().size(); i++) {
+                    node.inputs().set(i, Node.Null);
+                }
+                for (int i = 0; i < node.successors().size(); i++) {
+                    node.successors().set(i, Node.Null);
+                }
+            }
+        }
+        for (Node node : graph.getNodes()) {
+            if (!flood.isMarked(node)) {
+                node.delete();
+            }
+        }
+    }
+
+    private void iterateInputs() {
+        for (Node node : graph.getNodes()) {
+            if (node instanceof Local) {
+                flood.add(node);
+            }
+            if (flood.isMarked(node)) {
+                for (Node input : node.inputs()) {
+                    flood.add(input);
+                }
+            }
+        }
+        for (Node current : flood) {
+            for (Node input : current.inputs()) {
+                flood.add(input);
+            }
+        }
+    }
+
+    private void disconnectNodes() {
+        for (Node node : graph.getNodes()) {
+            if (!flood.isMarked(node)) {
+                for (int i = 0; i < node.inputs().size(); i++) {
+                    Node input = node.inputs().get(i);
+                    if (input != Node.Null && flood.isMarked(input)) {
+                        node.inputs().set(i, Node.Null);
+                    }
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DuplicationPhase.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.phases;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.graph.*;
+import com.oracle.max.graal.graph.*;
+
+/**
+ * Duplicates every node in the graph to test the implementation of the {@link com.oracle.max.graal.graph.Node#copy()} method in node subclasses.
+ */
+public class DuplicationPhase extends Phase {
+
+    @Override
+    protected void run(Graph graph) {
+
+        // Create duplicate graph.
+        CompilerGraph duplicate = new CompilerGraph(((CompilerGraph) graph).runtime());
+        Map<Node, Node> replacements = new HashMap<Node, Node>();
+        replacements.put(graph.start(), duplicate.start());
+        duplicate.addDuplicate(graph.getNodes(), replacements);
+
+        // Delete nodes in original graph.
+        for (Node n : graph.getNodes()) {
+            if (n != graph.start()) {
+                n.forceDelete();
+            }
+        }
+
+        // Copy nodes from duplicate back to original graph.
+        replacements.clear();
+        replacements.put(duplicate.start(), graph.start());
+        graph.addDuplicate(duplicate.getNodes(), replacements);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/EscapeAnalysisPhase.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,394 @@
+/*
+ * 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.max.graal.compiler.phases;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.compiler.graph.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.ir.Phi.PhiType;
+import com.oracle.max.graal.compiler.observer.*;
+import com.oracle.max.graal.compiler.schedule.*;
+import com.oracle.max.graal.compiler.value.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public class EscapeAnalysisPhase extends Phase {
+
+    public static class BlockExitState implements MergeableState<BlockExitState> {
+        public final Value[] fieldState;
+        public final VirtualObject virtualObject;
+        public FloatingNode virtualObjectField;
+
+        public BlockExitState(EscapeField[] fields, VirtualObject virtualObject) {
+            this.fieldState = new Value[fields.length];
+            this.virtualObject = virtualObject;
+            this.virtualObjectField = null;
+            for (int i = 0; i < fields.length; i++) {
+                fieldState[i] = Constant.defaultForKind(fields[i].kind(), virtualObject.graph());
+                virtualObjectField = new VirtualObjectField(virtualObject, virtualObjectField, fieldState[i], i, virtualObject.graph());
+            }
+        }
+
+        public BlockExitState(BlockExitState state) {
+            this.fieldState = state.fieldState.clone();
+            this.virtualObject = state.virtualObject;
+            this.virtualObjectField = state.virtualObjectField;
+        }
+
+        public void updateField(int fieldIndex) {
+            virtualObjectField = new VirtualObjectField(virtualObject, virtualObjectField, fieldState[fieldIndex], fieldIndex, virtualObject.graph());
+        }
+
+        @Override
+        public BlockExitState clone() {
+            return new BlockExitState(this);
+        }
+
+        @Override
+        public boolean merge(Merge merge, Collection<BlockExitState> withStates) {
+            Phi vobjPhi = null;
+            Phi[] valuePhis = new Phi[fieldState.length];
+            for (BlockExitState other : withStates) {
+                if (virtualObjectField != other.virtualObjectField && vobjPhi == null) {
+                    vobjPhi = new Phi(CiKind.Illegal, merge, PhiType.Virtual, virtualObject.graph());
+                    vobjPhi.addInput(virtualObjectField);
+                    virtualObjectField = vobjPhi;
+                }
+                for (int i2 = 0; i2 < fieldState.length; i2++) {
+                    if (fieldState[i2] != other.fieldState[i2] && valuePhis[i2] == null) {
+                        valuePhis[i2] = new Phi(fieldState[i2].kind, merge, PhiType.Value, virtualObject.graph());
+                        valuePhis[i2].addInput(fieldState[i2]);
+                        fieldState[i2] = valuePhis[i2];
+                    }
+                }
+            }
+            for (BlockExitState other : withStates) {
+                if (vobjPhi != null) {
+                    vobjPhi.addInput(other.virtualObjectField);
+                }
+                for (int i2 = 0; i2 < fieldState.length; i2++) {
+                    if (valuePhis[i2] != null) {
+                        valuePhis[i2].addInput(other.fieldState[i2]);
+                    }
+                }
+            }
+            assert vobjPhi == null || vobjPhi.valueCount() == withStates.size() + 1;
+            for (int i2 = 0; i2 < fieldState.length; i2++) {
+                if (valuePhis[i2] != null) {
+                    virtualObjectField = new VirtualObjectField(virtualObject, virtualObjectField, valuePhis[i2], i2, virtualObject.graph());
+                    assert valuePhis[i2].valueCount() == withStates.size() + 1;
+                }
+            }
+            return true;
+        }
+
+        @Override
+        public void loopBegin(LoopBegin loopBegin) {
+            Phi vobjPhi = null;
+            vobjPhi = new Phi(CiKind.Illegal, loopBegin, PhiType.Virtual, virtualObject.graph());
+            vobjPhi.addInput(virtualObjectField);
+            virtualObjectField = vobjPhi;
+            for (int i2 = 0; i2 < fieldState.length; i2++) {
+                Phi valuePhi = new Phi(fieldState[i2].kind, loopBegin, PhiType.Value, virtualObject.graph());
+                valuePhi.addInput(fieldState[i2]);
+                fieldState[i2] = valuePhi;
+                updateField(i2);
+            }
+        }
+
+        @Override
+        public void loopEnd(LoopEnd x, BlockExitState loopEndState) {
+            while (!(virtualObjectField instanceof Phi)) {
+                virtualObjectField = ((VirtualObjectField) virtualObjectField).lastState();
+            }
+            ((Phi) virtualObjectField).addInput(loopEndState.virtualObjectField);
+            assert ((Phi) virtualObjectField).valueCount() == 2;
+            for (int i2 = 0; i2 < fieldState.length; i2++) {
+                ((Phi) fieldState[i2]).addInput(loopEndState.fieldState[i2]);
+                assert ((Phi) fieldState[i2]).valueCount() == 2;
+            }
+        }
+
+        @Override
+        public void afterSplit(FixedNode node) {
+            // nothing to do...
+        }
+    }
+
+
+    public class EscapementFixup {
+
+        private List<Block> blocks;
+        private final Map<Object, Integer> fields = new HashMap<Object, Integer>();
+        private final Map<Block, BlockExitState> exitStates = new HashMap<Block, BlockExitState>();
+
+        private final EscapeOp op;
+        private final Graph graph;
+        private final Node node;
+        private EscapeField[] escapeFields;
+
+        public EscapementFixup(EscapeOp op, Graph graph, Node node) {
+            this.op = op;
+            this.graph = graph;
+            this.node = node;
+        }
+
+        public void apply() {
+            process();
+            removeAllocation();
+        }
+
+        public void removeAllocation() {
+            assert node instanceof FixedNodeWithNext;
+
+            escapeFields = op.fields(node);
+            for (int i = 0; i < escapeFields.length; i++) {
+                fields.put(escapeFields[i].representation(), i);
+            }
+            final VirtualObject virtual = new VirtualObject(((Value) node).exactType(), escapeFields, graph);
+            if (GraalOptions.TraceEscapeAnalysis || GraalOptions.PrintEscapeAnalysis) {
+                TTY.println("new virtual object: " + virtual);
+            }
+            node.replaceAtUsages(virtual);
+            final FixedNode next = ((FixedNodeWithNext) node).next();
+            node.replaceAndDelete(next);
+
+            final BlockExitState startState = new BlockExitState(escapeFields, virtual);
+            final PostOrderNodeIterator<?> iterator = new PostOrderNodeIterator<BlockExitState>(next, startState) {
+                @Override
+                protected void node(FixedNode node) {
+                    int changedField = op.updateState(virtual, node, fields, state.fieldState);
+                    if (changedField != -1) {
+                        state.updateField(changedField);
+                    }
+                    if (!node.isDeleted() && node instanceof StateSplit && ((StateSplit) node).stateAfter() != null) {
+                        if (state.virtualObjectField != null) {
+                            ((StateSplit) node).stateAfter().addVirtualObjectMapping(state.virtualObjectField);
+                        }
+                    }
+                }
+            };
+            iterator.apply();
+        }
+
+        private void process() {
+            ArrayList<Node> arrayList = new ArrayList<Node>(node.usages());
+            for (Node usage : arrayList) {
+                op.beforeUpdate(node, usage);
+            }
+        }
+    }
+
+    private final GraalCompilation compilation;
+    private final IR ir;
+
+    public EscapeAnalysisPhase(GraalCompilation compilation, IR ir) {
+        this.compilation = compilation;
+        this.ir = ir;
+    }
+
+    @Override
+    protected void run(Graph graph) {
+        for (Node node : graph.getNodes()) {
+            EscapeOp op = node.lookup(EscapeOp.class);
+            if (op != null && op.canAnalyze(node)) {
+                Set<Node> exits = new HashSet<Node>();
+                Set<Invoke> invokes = new HashSet<Invoke>();
+                int iterations = 0;
+
+                int minimumWeight = GraalOptions.ForcedInlineEscapeWeight;
+                do {
+                    double weight = analyze(op, node, exits, invokes);
+                    if (exits.size() != 0) {
+                        if (GraalOptions.TraceEscapeAnalysis || GraalOptions.PrintEscapeAnalysis) {
+                            TTY.println("%n####### escaping object: %d %s (%s) in %s", node.id(), node.shortName(), ((Value) node).exactType(), compilation.method);
+                            if (GraalOptions.TraceEscapeAnalysis) {
+                                TTY.print("%d: new value: %d %s, weight %d, escapes at ", iterations, node.id(), node.shortName(), weight);
+                                for (Node n : exits) {
+                                    TTY.print("%d %s, ", n.id(), n.shortName());
+                                }
+                                for (Node n : invokes) {
+                                    TTY.print("%d %s, ", n.id(), n.shortName());
+                                }
+                                TTY.println();
+                            }
+                        }
+                        break;
+                    }
+                    if (invokes.size() == 0) {
+
+                        if (compilation.compiler.isObserved()) {
+                            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "Before escape " + node.id(), graph, true, false));
+                        }
+                        if (GraalOptions.TraceEscapeAnalysis || GraalOptions.PrintEscapeAnalysis) {
+                            TTY.println("%n!!!!!!!! non-escaping object: %d %s (%s) in %s", node.id(), node.shortName(), ((Value) node).exactType(), compilation.method);
+                        }
+                        new EscapementFixup(op, graph, node).apply();
+                        if (compilation.compiler.isObserved()) {
+                            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After escape", graph, true, false));
+                        }
+                        new PhiSimplifier(graph);
+                        break;
+                    }
+                    if (weight < minimumWeight) {
+                        if (GraalOptions.TraceEscapeAnalysis || GraalOptions.PrintEscapeAnalysis) {
+                            TTY.println("%n####### possibly escaping object: %d in %s (insufficient weight for inlining)", node.id(), compilation.method);
+                        }
+                        break;
+                    }
+                    if (!GraalOptions.Inline) {
+                        break;
+                    }
+                    if (GraalOptions.TraceEscapeAnalysis || GraalOptions.PrintEscapeAnalysis) {
+                        TTY.println("Trying inlining to get a non-escaping object for %d", node.id());
+                    }
+                    new InliningPhase(compilation, ir, invokes).apply(graph);
+                    new DeadCodeEliminationPhase().apply(graph);
+                    if (node.isDeleted()) {
+                        if (GraalOptions.TraceEscapeAnalysis || GraalOptions.PrintEscapeAnalysis) {
+                            TTY.println("%n!!!!!!!! object died while performing escape analysis: %d %s (%s) in %s", node.id(), node.shortName(), ((Value) node).exactType(), compilation.method);
+                        }
+                        break;
+                    }
+                    exits.clear();
+                    invokes.clear();
+                } while (iterations++ < 3);
+            }
+        }
+    }
+
+    private double analyze(EscapeOp op, Node node, Collection<Node> exits, Collection<Invoke> invokes) {
+        double weight = 0;
+        for (Node usage : node.usages()) {
+            boolean escapes = op.escape(node, usage);
+            if (escapes) {
+                if (usage instanceof FrameState) {
+                    // nothing to do...
+                } else if (usage instanceof Invoke) {
+                    invokes.add((Invoke) usage);
+                } else {
+                    exits.add(usage);
+                    if (!GraalOptions.TraceEscapeAnalysis) {
+                        break;
+                    }
+                }
+            } else {
+                if (GraalOptions.ProbabilityAnalysis && usage instanceof FixedNode) {
+                    weight += ((FixedNode) usage).probability();
+                } else {
+                    weight++;
+                }
+            }
+        }
+        return weight;
+    }
+
+    public static class EscapeField {
+
+        private String name;
+        private Object representation;
+        private CiKind kind;
+
+        public EscapeField(String name, Object representation, CiKind kind) {
+            this.name = name;
+            this.representation = representation;
+            this.kind = kind;
+        }
+
+        public String name() {
+            return name;
+        }
+
+        public Object representation() {
+            return representation;
+        }
+
+        public CiKind kind() {
+            return kind;
+        }
+
+        @Override
+        public String toString() {
+            return name();
+        }
+    }
+
+    public abstract static class EscapeOp implements Op {
+
+        public abstract boolean canAnalyze(Node node);
+
+        public boolean escape(Node node, Node usage) {
+            if (usage instanceof IsNonNull) {
+                IsNonNull x = (IsNonNull) usage;
+                assert x.object() == node;
+                return false;
+            } else if (usage instanceof IsType) {
+                IsType x = (IsType) usage;
+                assert x.object() == node;
+                return false;
+            } else if (usage instanceof FrameState) {
+                FrameState x = (FrameState) usage;
+                assert x.inputs().contains(node);
+                return true;
+            } else if (usage instanceof AccessMonitor) {
+                AccessMonitor x = (AccessMonitor) usage;
+                assert x.object() == node;
+                return false;
+            } else {
+                return true;
+            }
+        }
+
+        public abstract EscapeField[] fields(Node node);
+
+        public void beforeUpdate(Node node, Node usage) {
+            if (usage instanceof IsNonNull) {
+                IsNonNull x = (IsNonNull) usage;
+                if (x.usages().size() == 1 && x.usages().get(0) instanceof FixedGuard) {
+                    FixedGuard guard = (FixedGuard) x.usages().get(0);
+                    guard.replaceAndDelete(guard.next());
+                }
+                x.delete();
+            } else if (usage instanceof IsType) {
+                IsType x = (IsType) usage;
+                assert x.type() == ((Value) node).exactType();
+                if (x.usages().size() == 1 && x.usages().get(0) instanceof FixedGuard) {
+                    FixedGuard guard = (FixedGuard) x.usages().get(0);
+                    guard.replaceAndDelete(guard.next());
+                }
+                x.delete();
+            } else if (usage instanceof AccessMonitor) {
+                AccessMonitor x = (AccessMonitor) usage;
+                x.replaceAndDelete(x.next());
+            }
+        }
+
+        public abstract int updateState(Node node, Node current, Map<Object, Integer> fieldIndex, Value[] fieldState);
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GlobalValueNumberingPhase.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,57 @@
+/*
+ * 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.max.graal.compiler.phases;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+
+/**
+ * Duplicates every node in the graph to test the implementation of the {@link com.oracle.max.graal.graph.Node#copy()} method in node subclasses.
+ */
+public class GlobalValueNumberingPhase extends Phase {
+
+    @Override
+    protected void run(Graph graph) {
+        NodeBitMap visited = graph.createNodeBitMap();
+        for (Node n : graph.getNodes()) {
+            apply(n, visited);
+        }
+    }
+
+    private void apply(Node n, NodeBitMap visited) {
+        if (n != null && !visited.isMarked(n)) {
+            visited.mark(n);
+            for (Node input : n.inputs()) {
+                apply(input, visited);
+            }
+            Node newNode = n.graph().ideal(n);
+            if (newNode != n) {
+                GraalMetrics.GlobalValueNumberingHits++;
+                if (GraalOptions.TraceGVN) {
+                    TTY.println("GVN applied and new node is " + newNode);
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,1693 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.phases;
+
+import static com.sun.cri.bytecode.Bytecodes.*;
+import static java.lang.reflect.Modifier.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.graph.*;
+import com.oracle.max.graal.compiler.graph.BlockMap.Block;
+import com.oracle.max.graal.compiler.graph.BlockMap.BranchOverride;
+import com.oracle.max.graal.compiler.graph.BlockMap.DeoptBlock;
+import com.oracle.max.graal.compiler.graph.BlockMap.ExceptionBlock;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.ir.Deoptimize.DeoptAction;
+import com.oracle.max.graal.compiler.schedule.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.compiler.util.LoopUtil.Loop;
+import com.oracle.max.graal.compiler.value.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+import com.sun.cri.ri.RiType.Representation;
+
+/**
+ * The {@code GraphBuilder} class parses the bytecode of a method and builds the IR graph.
+ * A number of optimizations may be performed during parsing of the bytecode, including value
+ * numbering, inlining, constant folding, strength reduction, etc.
+ */
+public final class GraphBuilderPhase extends Phase {
+
+    /**
+     * The minimum value to which {@link GraalOptions#TraceBytecodeParserLevel} must be set to trace
+     * the bytecode instructions as they are parsed.
+     */
+    public static final int TRACELEVEL_INSTRUCTIONS = 1;
+
+    /**
+     * The minimum value to which {@link GraalOptions#TraceBytecodeParserLevel} must be set to trace
+     * the frame state before each bytecode instruction as it is parsed.
+     */
+    public static final int TRACELEVEL_STATE = 2;
+
+    private final GraalCompilation compilation;
+    private CompilerGraph graph;
+
+    private final CiStatistics stats;
+    private final RiRuntime runtime;
+    private final RiMethod method;
+    private final RiConstantPool constantPool;
+    private RiExceptionHandler[] exceptionHandlers;
+
+    private final BytecodeStream stream;           // the bytecode stream
+    private final LogStream log;
+    private FrameStateBuilder frameState;          // the current execution state
+
+    // bci-to-block mapping
+    private Block[] blockFromBci;
+    private ArrayList<Block> blockList;
+    private HashMap<Integer, BranchOverride> branchOverride;
+
+    private int nextBlockNumber;
+
+    private Value methodSynchronizedObject;
+    private CiExceptionHandler unwindHandler;
+
+    private ExceptionBlock unwindBlock;
+    private Block returnBlock;
+
+    private boolean storeResultGraph;
+
+    // the worklist of blocks, sorted by depth first number
+    private final PriorityQueue<Block> workList = new PriorityQueue<Block>(10, new Comparator<Block>() {
+        public int compare(Block o1, Block o2) {
+            return o1.blockID - o2.blockID;
+        }
+    });
+
+    private FixedNodeWithNext lastInstr;                 // the last instruction added
+
+    private final Set<Block> blocksOnWorklist = new HashSet<Block>();
+    private final Set<Block> blocksVisited = new HashSet<Block>();
+
+    public static final Map<RiMethod, CompilerGraph> cachedGraphs = new WeakHashMap<RiMethod, CompilerGraph>();
+
+    /**
+     * Creates a new, initialized, {@code GraphBuilder} instance for a given compilation.
+     *
+     * @param compilation the compilation
+     * @param ir the IR to build the graph into
+     * @param graph
+     */
+    public GraphBuilderPhase(GraalCompilation compilation, RiMethod method, boolean inline) {
+        super(inline ? "BuildInlineGraph" : "BuildGraph");
+        this.compilation = compilation;
+
+        setDetailedName(getName() + " " + method.holder().name() + "." + method.name() + method.signature().asString());
+
+        this.runtime = compilation.runtime;
+        this.method = method;
+        this.stats = compilation.stats;
+        this.log = GraalOptions.TraceBytecodeParserLevel > 0 ? new LogStream(TTY.out()) : null;
+        this.stream = new BytecodeStream(method.code());
+
+        this.constantPool = runtime.getConstantPool(method);
+        this.storeResultGraph = GraalOptions.CacheGraphs;
+    }
+
+    @Override
+    protected void run(Graph graph) {
+        assert graph != null;
+        this.graph = (CompilerGraph) graph;
+        this.frameState = new FrameStateBuilder(method, graph);
+        build();
+    }
+
+    /**
+     * Builds the graph for a the specified {@code IRScope}.
+     *
+     * @param createUnwind setting this to true will always generate an unwind block, even if there is no exception
+     *            handler and the method is not synchronized
+     */
+    private void build() {
+        if (log != null) {
+            log.println();
+            log.println("Compiling " + method);
+        }
+
+        // 2. compute the block map, setup exception handlers and get the entrypoint(s)
+        BlockMap blockMap = compilation.getBlockMap(method);
+        this.branchOverride = blockMap.branchOverride;
+
+        exceptionHandlers = blockMap.exceptionHandlers();
+        blockList = new ArrayList<Block>(blockMap.blocks);
+        blockFromBci = new Block[method.codeSize()];
+        for (int i = 0; i < blockList.size(); i++) {
+            int blockID = nextBlockNumber();
+            assert blockID == i;
+            Block block = blockList.get(i);
+            if (block.startBci >= 0 && !(block instanceof BlockMap.DeoptBlock)) {
+                blockFromBci[block.startBci] = block;
+            }
+        }
+
+        // 1. create the start block
+        Block startBlock = nextBlock(FixedNodeWithNext.SYNCHRONIZATION_ENTRY_BCI);
+        markOnWorkList(startBlock);
+        lastInstr = (FixedNodeWithNext) createTarget(startBlock, frameState);
+        graph.start().setNext(lastInstr);
+
+        if (isSynchronized(method.accessFlags())) {
+            // 4A.1 add a monitor enter to the start block
+            methodSynchronizedObject = synchronizedObject(frameState, method);
+            genMonitorEnter(methodSynchronizedObject, FixedNodeWithNext.SYNCHRONIZATION_ENTRY_BCI);
+        }
+
+        // 4B.1 simply finish the start block
+        finishStartBlock(startBlock);
+        unwindHandler = new CiExceptionHandler(0, method.code().length, FixedNodeWithNext.SYNCHRONIZATION_ENTRY_BCI, 0, null);
+
+        // 5. SKIPPED: look for intrinsics
+
+        // 6B.1 do the normal parsing
+        addToWorkList(blockFromBci[0]);
+        iterateAllBlocks();
+
+        List<Loop> loops = LoopUtil.computeLoops(graph);
+        NodeBitMap loopExits = graph.createNodeBitMap();
+        for (Loop loop : loops) {
+            loopExits.setUnion(loop.exits());
+        }
+
+        // remove Placeholders
+        for (Node n : graph.getNodes()) {
+            if (n instanceof Placeholder && !loopExits.isMarked(n)) {
+                Placeholder p = (Placeholder) n;
+                p.replaceAndDelete(p.next());
+            }
+        }
+
+        // remove FrameStates
+        for (Node n : graph.getNodes()) {
+            if (n instanceof FrameState) {
+                if (n.usages().size() == 0 && n.predecessors().size() == 0) {
+                    n.delete();
+                }
+            }
+        }
+
+        if (storeResultGraph) {
+            // Create duplicate graph.
+            CompilerGraph duplicate = new CompilerGraph(null);
+            Map<Node, Node> replacements = new HashMap<Node, Node>();
+            replacements.put(graph.start(), duplicate.start());
+            duplicate.addDuplicate(graph.getNodes(), replacements);
+
+            cachedGraphs.put(method, duplicate);
+        }
+    }
+
+    private int nextBlockNumber() {
+        stats.blockCount++;
+        return nextBlockNumber++;
+    }
+
+    private Block nextBlock(int bci) {
+        Block block = new Block();
+        block.startBci = bci;
+        block.endBci = bci;
+        block.blockID = nextBlockNumber();
+        return block;
+    }
+
+    private Block unwindBlock(int bci) {
+        if (unwindBlock == null) {
+            unwindBlock = new ExceptionBlock();
+            unwindBlock.startBci = -1;
+            unwindBlock.endBci = -1;
+            unwindBlock.deoptBci = bci;
+            unwindBlock.blockID = nextBlockNumber();
+            addToWorkList(unwindBlock);
+        }
+        return unwindBlock;
+    }
+
+    private Block returnBlock(int bci) {
+        if (returnBlock == null) {
+            returnBlock = new Block();
+            returnBlock.startBci = bci;
+            returnBlock.endBci = bci;
+            returnBlock.blockID = nextBlockNumber();
+            addToWorkList(returnBlock);
+        }
+        return returnBlock;
+    }
+
+    private void markOnWorkList(Block block) {
+        blocksOnWorklist.add(block);
+    }
+
+    private boolean isOnWorkList(Block block) {
+        return blocksOnWorklist.contains(block);
+    }
+
+    private void markVisited(Block block) {
+        blocksVisited.add(block);
+    }
+
+    private boolean isVisited(Block block) {
+        return blocksVisited.contains(block);
+    }
+
+    private void finishStartBlock(Block startBlock) {
+        assert bci() == 0;
+        appendGoto(createTargetAt(0, frameState));
+    }
+
+    public void mergeOrClone(Block target, FrameStateAccess newState) {
+        StateSplit first = (StateSplit) target.firstInstruction;
+
+        if (target.isLoopHeader && isVisited(target)) {
+            first = (StateSplit) loopBegin(target).loopEnd().singlePredecessor();
+        }
+
+        int bci = target.startBci;
+        if (target instanceof ExceptionBlock) {
+            bci = ((ExceptionBlock) target).deoptBci;
+        }
+
+        FrameState existingState = first.stateAfter();
+
+        if (existingState == null) {
+            // copy state because it is modified
+            first.setStateAfter(newState.duplicate(bci));
+        } else {
+            if (!GraalOptions.AssumeVerifiedBytecode && !existingState.isCompatibleWith(newState)) {
+                // stacks or locks do not match--bytecodes would not verify
+                TTY.println(existingState.toString());
+                TTY.println(newState.duplicate(0).toString());
+                throw new CiBailout("stack or locks do not match");
+            }
+            assert existingState.localsSize() == newState.localsSize();
+            assert existingState.stackSize() == newState.stackSize();
+
+            if (first instanceof Placeholder) {
+                Placeholder p = (Placeholder) first;
+                if (p.predecessors().size() == 0) {
+                    p.setStateAfter(newState.duplicate(bci));
+                    return;
+                } else {
+                    Merge merge = new Merge(graph);
+                    assert p.predecessors().size() == 1 : "predecessors size: " + p.predecessors().size();
+                    FixedNode next = p.next();
+                    EndNode end = new EndNode(graph);
+                    p.setNext(end);
+                    merge.setNext(next);
+                    merge.addEnd(end);
+                    merge.setStateAfter(existingState);
+                    p.setStateAfter(existingState.duplicate(bci));
+                    if (!(next instanceof LoopEnd)) {
+                        target.firstInstruction = merge;
+                    }
+                    first = merge;
+                }
+            }
+
+            existingState.merge((Merge) first, newState);
+        }
+    }
+
+    private void insertLoopPhis(LoopBegin loopBegin, FrameState newState) {
+        int stackSize = newState.stackSize();
+        for (int i = 0; i < stackSize; i++) {
+            // always insert phis for the stack
+            Value x = newState.stackAt(i);
+            if (x != null) {
+                newState.setupPhiForStack(loopBegin, i).addInput(x);
+            }
+        }
+        int localsSize = newState.localsSize();
+        for (int i = 0; i < localsSize; i++) {
+            Value x = newState.localAt(i);
+            if (x != null) {
+                newState.setupPhiForLocal(loopBegin, i).addInput(x);
+            }
+        }
+    }
+
+    public BytecodeStream stream() {
+        return stream;
+    }
+
+    public int bci() {
+        return stream.currentBCI();
+    }
+
+    private void loadLocal(int index, CiKind kind) {
+        frameState.push(kind, frameState.loadLocal(index));
+    }
+
+    private void storeLocal(CiKind kind, int index) {
+        frameState.storeLocal(index, frameState.pop(kind));
+    }
+
+    public boolean covers(RiExceptionHandler handler, int bci) {
+        return handler.startBCI() <= bci && bci < handler.endBCI();
+    }
+
+    public boolean isCatchAll(RiExceptionHandler handler) {
+        return handler.catchTypeCPI() == 0;
+    }
+
+    private FixedNode handleException(Value exceptionObject, int bci) {
+        assert bci == FixedNodeWithNext.SYNCHRONIZATION_ENTRY_BCI || bci == bci() : "invalid bci";
+
+        if (GraalOptions.UseExceptionProbability && method.invocationCount() > GraalOptions.MatureInvocationCount) {
+            if (exceptionObject == null && method.exceptionProbability(bci) == 0) {
+                return null;
+            }
+        }
+
+        RiExceptionHandler firstHandler = null;
+        // join with all potential exception handlers
+        if (exceptionHandlers != null) {
+            for (RiExceptionHandler handler : exceptionHandlers) {
+                // if the handler covers this bytecode index, add it to the list
+                if (covers(handler, bci)) {
+                    firstHandler = handler;
+                    break;
+                }
+            }
+        }
+
+        if (firstHandler == null) {
+            firstHandler = unwindHandler;
+        }
+
+        if (firstHandler != null) {
+            compilation.setHasExceptionHandlers();
+
+            Block dispatchBlock = null;
+            for (Block block : blockList) {
+                if (block instanceof ExceptionBlock) {
+                    ExceptionBlock excBlock = (ExceptionBlock) block;
+                    if (excBlock.handler == firstHandler) {
+                        dispatchBlock = block;
+                        break;
+                    }
+                }
+            }
+            // if there's no dispatch block then the catch block needs to be a catch all
+            if (dispatchBlock == null) {
+                assert isCatchAll(firstHandler);
+                int handlerBCI = firstHandler.handlerBCI();
+                if (handlerBCI == FixedNodeWithNext.SYNCHRONIZATION_ENTRY_BCI) {
+                    dispatchBlock = unwindBlock(bci);
+                } else {
+                    dispatchBlock = blockFromBci[handlerBCI];
+                }
+            }
+            Placeholder p = new Placeholder(graph);
+            p.setStateAfter(frameState.duplicateWithoutStack(bci));
+
+            Value currentExceptionObject;
+            ExceptionObject newObj = null;
+            if (exceptionObject == null) {
+                newObj = new ExceptionObject(graph);
+                currentExceptionObject = newObj;
+            } else {
+                currentExceptionObject = exceptionObject;
+            }
+            FrameState stateWithException = frameState.duplicateWithException(bci, currentExceptionObject);
+            if (newObj != null) {
+                newObj.setStateAfter(stateWithException);
+            }
+            FixedNode target = createTarget(dispatchBlock, stateWithException);
+            if (exceptionObject == null) {
+                ExceptionObject eObj = (ExceptionObject) currentExceptionObject;
+                eObj.setNext(target);
+                p.setNext(eObj);
+            } else {
+                p.setNext(target);
+            }
+            return p;
+        }
+        return null;
+    }
+
+    private void genLoadConstant(int cpi) {
+        Object con = constantPool.lookupConstant(cpi);
+
+        if (con instanceof RiType) {
+            // this is a load of class constant which might be unresolved
+            RiType riType = (RiType) con;
+            if (!riType.isResolved()) {
+                storeResultGraph = false;
+                append(new Deoptimize(DeoptAction.InvalidateRecompile, graph));
+                frameState.push(CiKind.Object, append(Constant.forObject(null, graph)));
+            } else {
+                frameState.push(CiKind.Object, append(new Constant(riType.getEncoding(Representation.JavaClass), graph)));
+            }
+        } else if (con instanceof CiConstant) {
+            CiConstant constant = (CiConstant) con;
+            frameState.push(constant.kind.stackKind(), appendConstant(constant));
+        } else {
+            throw new Error("lookupConstant returned an object of incorrect type");
+        }
+    }
+
+    private void genLoadIndexed(CiKind kind) {
+        Value index = frameState.ipop();
+        Value array = frameState.apop();
+        Value length = append(new ArrayLength(array, graph));
+        Value v = append(new LoadIndexed(array, index, length, kind, graph));
+        frameState.push(kind.stackKind(), v);
+    }
+
+    private void genStoreIndexed(CiKind kind) {
+        Value value = frameState.pop(kind.stackKind());
+        Value index = frameState.ipop();
+        Value array = frameState.apop();
+        Value length = append(new ArrayLength(array, graph));
+        StoreIndexed result = new StoreIndexed(array, index, length, kind, value, graph);
+        append(result);
+    }
+
+    private void stackOp(int opcode) {
+        switch (opcode) {
+            case POP: {
+                frameState.xpop();
+                break;
+            }
+            case POP2: {
+                frameState.xpop();
+                frameState.xpop();
+                break;
+            }
+            case DUP: {
+                Value w = frameState.xpop();
+                frameState.xpush(w);
+                frameState.xpush(w);
+                break;
+            }
+            case DUP_X1: {
+                Value w1 = frameState.xpop();
+                Value w2 = frameState.xpop();
+                frameState.xpush(w1);
+                frameState.xpush(w2);
+                frameState.xpush(w1);
+                break;
+            }
+            case DUP_X2: {
+                Value w1 = frameState.xpop();
+                Value w2 = frameState.xpop();
+                Value w3 = frameState.xpop();
+                frameState.xpush(w1);
+                frameState.xpush(w3);
+                frameState.xpush(w2);
+                frameState.xpush(w1);
+                break;
+            }
+            case DUP2: {
+                Value w1 = frameState.xpop();
+                Value w2 = frameState.xpop();
+                frameState.xpush(w2);
+                frameState.xpush(w1);
+                frameState.xpush(w2);
+                frameState.xpush(w1);
+                break;
+            }
+            case DUP2_X1: {
+                Value w1 = frameState.xpop();
+                Value w2 = frameState.xpop();
+                Value w3 = frameState.xpop();
+                frameState.xpush(w2);
+                frameState.xpush(w1);
+                frameState.xpush(w3);
+                frameState.xpush(w2);
+                frameState.xpush(w1);
+                break;
+            }
+            case DUP2_X2: {
+                Value w1 = frameState.xpop();
+                Value w2 = frameState.xpop();
+                Value w3 = frameState.xpop();
+                Value w4 = frameState.xpop();
+                frameState.xpush(w2);
+                frameState.xpush(w1);
+                frameState.xpush(w4);
+                frameState.xpush(w3);
+                frameState.xpush(w2);
+                frameState.xpush(w1);
+                break;
+            }
+            case SWAP: {
+                Value w1 = frameState.xpop();
+                Value w2 = frameState.xpop();
+                frameState.xpush(w1);
+                frameState.xpush(w2);
+                break;
+            }
+            default:
+                throw Util.shouldNotReachHere();
+        }
+
+    }
+
+    private void genArithmeticOp(CiKind kind, int opcode) {
+        genArithmeticOp(kind, opcode, false);
+    }
+
+    private void genArithmeticOp(CiKind result, int opcode, boolean canTrap) {
+        Value y = frameState.pop(result);
+        Value x = frameState.pop(result);
+        boolean isStrictFP = isStrict(method.accessFlags());
+        Arithmetic v;
+        switch(opcode){
+            case IADD:
+            case LADD: v = new IntegerAdd(result, x, y, graph); break;
+            case FADD:
+            case DADD: v = new FloatAdd(result, x, y, isStrictFP, graph); break;
+            case ISUB:
+            case LSUB: v = new IntegerSub(result, x, y, graph); break;
+            case FSUB:
+            case DSUB: v = new FloatSub(result, x, y, isStrictFP, graph); break;
+            case IMUL:
+            case LMUL: v = new IntegerMul(result, x, y, graph); break;
+            case FMUL:
+            case DMUL: v = new FloatMul(result, x, y, isStrictFP, graph); break;
+            case IDIV:
+            case LDIV: v = new IntegerDiv(result, x, y, graph); break;
+            case FDIV:
+            case DDIV: v = new FloatDiv(result, x, y, isStrictFP, graph); break;
+            case IREM:
+            case LREM: v = new IntegerRem(result, x, y, graph); break;
+            case FREM:
+            case DREM: v = new FloatRem(result, x, y, isStrictFP, graph); break;
+            default:
+                throw new CiBailout("should not reach");
+        }
+        Value result1 = append(v);
+        if (canTrap) {
+            append(new ValueAnchor(result1, graph));
+        }
+        frameState.push(result, result1);
+    }
+
+    private void genNegateOp(CiKind kind) {
+        frameState.push(kind, append(new Negate(frameState.pop(kind), graph)));
+    }
+
+    private void genShiftOp(CiKind kind, int opcode) {
+        Value s = frameState.ipop();
+        Value x = frameState.pop(kind);
+        Shift v;
+        switch(opcode){
+            case ISHL:
+            case LSHL: v = new LeftShift(kind, x, s, graph); break;
+            case ISHR:
+            case LSHR: v = new RightShift(kind, x, s, graph); break;
+            case IUSHR:
+            case LUSHR: v = new UnsignedRightShift(kind, x, s, graph); break;
+            default:
+                throw new CiBailout("should not reach");
+        }
+        frameState.push(kind, append(v));
+    }
+
+    private void genLogicOp(CiKind kind, int opcode) {
+        Value y = frameState.pop(kind);
+        Value x = frameState.pop(kind);
+        Logic v;
+        switch(opcode){
+            case IAND:
+            case LAND: v = new And(kind, x, y, graph); break;
+            case IOR:
+            case LOR: v = new Or(kind, x, y, graph); break;
+            case IXOR:
+            case LXOR: v = new Xor(kind, x, y, graph); break;
+            default:
+                throw new CiBailout("should not reach");
+        }
+        frameState.push(kind, append(v));
+    }
+
+    private void genCompareOp(CiKind kind, int opcode, CiKind resultKind) {
+        Value y = frameState.pop(kind);
+        Value x = frameState.pop(kind);
+        Value value = append(new NormalizeCompare(opcode, resultKind, x, y, graph));
+        if (!resultKind.isVoid()) {
+            frameState.ipush(value);
+        }
+    }
+
+    private void genConvert(int opcode, CiKind from, CiKind to) {
+        CiKind tt = to.stackKind();
+        frameState.push(tt, append(new Convert(opcode, frameState.pop(from.stackKind()), tt, graph)));
+    }
+
+    private void genIncrement() {
+        int index = stream().readLocalIndex();
+        int delta = stream().readIncrement();
+        Value x = frameState.localAt(index);
+        Value y = append(Constant.forInt(delta, graph));
+        frameState.storeLocal(index, append(new IntegerAdd(CiKind.Int, x, y, graph)));
+    }
+
+    private void genGoto(int fromBCI, int toBCI) {
+        appendGoto(createTargetAt(toBCI, frameState));
+    }
+
+    private void ifNode(Value x, Condition cond, Value y) {
+        assert !x.isDeleted() && !y.isDeleted();
+        double probability = method.branchProbability(bci());
+        if (probability < 0) {
+            if (GraalOptions.TraceProbability) {
+                TTY.println("missing probability in " + method + " at bci " + bci());
+            }
+            probability = 0.5;
+        }
+
+        If ifNode = new If(new Compare(x, cond, y, graph), probability, graph);
+        append(ifNode);
+        BlockMap.BranchOverride override = branchOverride.get(bci());
+        FixedNode tsucc;
+        if (override == null || override.taken == false) {
+            tsucc = createTargetAt(stream().readBranchDest(), frameState);
+        } else {
+            tsucc = createTarget(override.block, frameState);
+        }
+        ifNode.setBlockSuccessor(0, tsucc);
+        FixedNode fsucc;
+        if (override == null || override.taken == true) {
+            fsucc = createTargetAt(stream().nextBCI(), frameState);
+        } else {
+            fsucc = createTarget(override.block, frameState);
+        }
+        ifNode.setBlockSuccessor(1, fsucc);
+    }
+
+    private void genIfZero(Condition cond) {
+        Value y = appendConstant(CiConstant.INT_0);
+        Value x = frameState.ipop();
+        ifNode(x, cond, y);
+    }
+
+    private void genIfNull(Condition cond) {
+        Value y = appendConstant(CiConstant.NULL_OBJECT);
+        Value x = frameState.apop();
+        ifNode(x, cond, y);
+    }
+
+    private void genIfSame(CiKind kind, Condition cond) {
+        Value y = frameState.pop(kind);
+        Value x = frameState.pop(kind);
+        assert !x.isDeleted() && !y.isDeleted();
+        ifNode(x, cond, y);
+    }
+
+    private void genThrow(int bci) {
+        Value exception = frameState.apop();
+        FixedGuard node = new FixedGuard(new IsNonNull(exception, graph), graph);
+        append(node);
+
+        FixedNode entry = handleException(exception, bci);
+        if (entry != null) {
+            append(entry);
+        } else {
+            appendGoto(createTarget(unwindBlock(bci), frameState.duplicateWithException(bci, exception)));
+        }
+    }
+
+    private void genCheckCast() {
+        int cpi = stream().readCPI();
+        RiType type = constantPool.lookupType(cpi, CHECKCAST);
+        Constant typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, type, type.isResolved());
+        Value object = frameState.apop();
+        if (typeInstruction != null) {
+//            InstanceOf instanceOf = new InstanceOf(typeInstruction, object, true, graph);
+//            FixedGuard fixedGuard = new FixedGuard(instanceOf, graph);
+//            append(fixedGuard);
+//            CastNode castNode = new CastNode(object.kind, object, graph);
+//            castNode.inputs().add(fixedGuard);
+//            frameState.apush(castNode);
+            frameState.apush(new CheckCast(typeInstruction, object, graph));
+        } else {
+            frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
+        }
+    }
+
+    private void genInstanceOf() {
+        int cpi = stream().readCPI();
+        RiType type = constantPool.lookupType(cpi, INSTANCEOF);
+        Constant typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, type, type.isResolved());
+        Value object = frameState.apop();
+        if (typeInstruction != null) {
+            frameState.ipush(append(new MaterializeNode(new InstanceOf(typeInstruction, object, false, graph), graph)));
+        } else {
+            frameState.ipush(appendConstant(CiConstant.INT_0));
+        }
+    }
+
+    void genNewInstance(int cpi) {
+        RiType type = constantPool.lookupType(cpi, NEW);
+        if (type.isResolved()) {
+            NewInstance n = new NewInstance(type, cpi, constantPool, graph);
+            frameState.apush(append(n));
+        } else {
+            storeResultGraph = false;
+            append(new Deoptimize(DeoptAction.InvalidateRecompile, graph));
+            frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
+        }
+    }
+
+    private void genNewTypeArray(int typeCode) {
+        CiKind kind = CiKind.fromArrayTypeCode(typeCode);
+        RiType elementType = runtime.asRiType(kind);
+        NewTypeArray nta = new NewTypeArray(frameState.ipop(), elementType, graph);
+        frameState.apush(append(nta));
+    }
+
+    private void genNewObjectArray(int cpi) {
+        RiType type = constantPool.lookupType(cpi, ANEWARRAY);
+        Value length = frameState.ipop();
+        if (type.isResolved()) {
+            NewArray n = new NewObjectArray(type, length, graph);
+            frameState.apush(append(n));
+        } else {
+            storeResultGraph = false;
+            append(new Deoptimize(DeoptAction.InvalidateRecompile, graph));
+            frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
+        }
+
+    }
+
+    private void genNewMultiArray(int cpi) {
+        RiType type = constantPool.lookupType(cpi, MULTIANEWARRAY);
+        int rank = stream().readUByte(bci() + 3);
+        Value[] dims = new Value[rank];
+        for (int i = rank - 1; i >= 0; i--) {
+            dims[i] = frameState.ipop();
+        }
+        if (type.isResolved()) {
+            NewArray n = new NewMultiArray(type, dims, cpi, constantPool, graph);
+            frameState.apush(append(n));
+        } else {
+            storeResultGraph = false;
+            append(new Deoptimize(DeoptAction.InvalidateRecompile, graph));
+            frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
+        }
+    }
+
+    private void genGetField(int cpi, RiField field) {
+        CiKind kind = field.kind();
+        Value receiver = frameState.apop();
+        if (field.isResolved() && field.holder().isInitialized()) {
+            LoadField load = new LoadField(receiver, field, graph);
+            appendOptimizedLoadField(kind, load);
+        } else {
+            storeResultGraph = false;
+            append(new Deoptimize(DeoptAction.InvalidateRecompile, graph));
+            frameState.push(kind.stackKind(), append(Constant.defaultForKind(kind, graph)));
+        }
+    }
+
+    private void genPutField(int cpi, RiField field) {
+        Value value = frameState.pop(field.kind().stackKind());
+        Value receiver = frameState.apop();
+        if (field.isResolved() && field.holder().isInitialized()) {
+            StoreField store = new StoreField(receiver, field, value, graph);
+            appendOptimizedStoreField(store);
+        } else {
+            storeResultGraph = false;
+            append(new Deoptimize(DeoptAction.InvalidateRecompile, graph));
+        }
+    }
+
+    private void genGetStatic(int cpi, RiField field) {
+        RiType holder = field.holder();
+        boolean isInitialized = field.isResolved() && field.holder().isInitialized();
+        CiConstant constantValue = null;
+        if (isInitialized) {
+            constantValue = field.constantValue(null);
+        }
+        if (constantValue != null) {
+            frameState.push(constantValue.kind.stackKind(), appendConstant(constantValue));
+        } else {
+            Value container = genTypeOrDeopt(RiType.Representation.StaticFields, holder, isInitialized);
+            CiKind kind = field.kind();
+            if (container != null) {
+                LoadField load = new LoadField(container, field, graph);
+                appendOptimizedLoadField(kind, load);
+            } else {
+                // deopt will be generated by genTypeOrDeopt, not needed here
+                frameState.push(kind.stackKind(), append(Constant.defaultForKind(kind, graph)));
+            }
+        }
+    }
+
+    private void genPutStatic(int cpi, RiField field) {
+        RiType holder = field.holder();
+        Value container = genTypeOrDeopt(RiType.Representation.StaticFields, holder, field.isResolved() && field.holder().isInitialized());
+        Value value = frameState.pop(field.kind().stackKind());
+        if (container != null) {
+            StoreField store = new StoreField(container, field, value, graph);
+            appendOptimizedStoreField(store);
+        } else {
+            // deopt will be generated by genTypeOrDeopt, not needed here
+        }
+    }
+
+    private Constant genTypeOrDeopt(RiType.Representation representation, RiType holder, boolean initialized) {
+        if (initialized) {
+            return appendConstant(holder.getEncoding(representation));
+        } else {
+            storeResultGraph = false;
+            append(new Deoptimize(DeoptAction.InvalidateRecompile, graph));
+            return null;
+        }
+    }
+
+    private void appendOptimizedStoreField(StoreField store) {
+        append(store);
+    }
+
+    private void appendOptimizedLoadField(CiKind kind, LoadField load) {
+        // append the load to the instruction
+        Value optimized = append(load);
+        frameState.push(kind.stackKind(), optimized);
+    }
+
+    private void genInvokeStatic(RiMethod target, int cpi, RiConstantPool constantPool) {
+        RiType holder = target.holder();
+        boolean isInitialized = target.isResolved() && holder.isInitialized();
+        if (!isInitialized && GraalOptions.ResolveClassBeforeStaticInvoke) {
+            // Re-use the same resolution code as for accessing a static field. Even though
+            // the result of resolution is not used by the invocation (only the side effect
+            // of initialization is required), it can be commoned with static field accesses.
+            genTypeOrDeopt(RiType.Representation.StaticFields, holder, isInitialized);
+        }
+        Value[] args = frameState.popArguments(target.signature().argumentSlots(false));
+        appendInvoke(INVOKESTATIC, target, args, cpi, constantPool);
+    }
+
+    private void genInvokeInterface(RiMethod target, int cpi, RiConstantPool constantPool) {
+        Value[] args = frameState.popArguments(target.signature().argumentSlots(true));
+        genInvokeIndirect(INVOKEINTERFACE, target, args, cpi, constantPool);
+
+    }
+
+    private void genInvokeVirtual(RiMethod target, int cpi, RiConstantPool constantPool) {
+        Value[] args = frameState.popArguments(target.signature().argumentSlots(true));
+        genInvokeIndirect(INVOKEVIRTUAL, target, args, cpi, constantPool);
+
+    }
+
+    private void genInvokeSpecial(RiMethod target, RiType knownHolder, int cpi, RiConstantPool constantPool) {
+        assert target != null;
+        assert target.signature() != null;
+        Value[] args = frameState.popArguments(target.signature().argumentSlots(true));
+        invokeDirect(target, args, knownHolder, cpi, constantPool);
+
+    }
+
+    private void genInvokeIndirect(int opcode, RiMethod target, Value[] args, int cpi, RiConstantPool constantPool) {
+        Value receiver = args[0];
+        // attempt to devirtualize the call
+        if (target.isResolved()) {
+            RiType klass = target.holder();
+
+            // 0. check for trivial cases
+            if (target.canBeStaticallyBound() && !isAbstract(target.accessFlags())) {
+                // check for trivial cases (e.g. final methods, nonvirtual methods)
+                invokeDirect(target, args, target.holder(), cpi, constantPool);
+                return;
+            }
+            // 1. check if the exact type of the receiver can be determined
+            RiType exact = getExactType(klass, receiver);
+            if (exact != null && exact.isResolved()) {
+                // either the holder class is exact, or the receiver object has an exact type
+                invokeDirect(exact.resolveMethodImpl(target), args, exact, cpi, constantPool);
+                return;
+            }
+        }
+        // devirtualization failed, produce an actual invokevirtual
+        appendInvoke(opcode, target, args, cpi, constantPool);
+    }
+
+    private CiKind returnKind(RiMethod target) {
+        return target.signature().returnKind();
+    }
+
+    private void invokeDirect(RiMethod target, Value[] args, RiType knownHolder, int cpi, RiConstantPool constantPool) {
+        appendInvoke(INVOKESPECIAL, target, args, cpi, constantPool);
+    }
+
+    private void appendInvoke(int opcode, RiMethod target, Value[] args, int cpi, RiConstantPool constantPool) {
+        CiKind resultType = returnKind(target);
+        if (GraalOptions.DeoptALot) {
+            storeResultGraph = false;
+            Deoptimize deoptimize = new Deoptimize(DeoptAction.None, graph);
+            deoptimize.setMessage("invoke " + target.name());
+            append(deoptimize);
+            frameState.pushReturn(resultType, Constant.defaultForKind(resultType, graph));
+        } else {
+            Invoke invoke = new Invoke(bci(), opcode, resultType.stackKind(), args, target, target.signature().returnType(method.holder()), graph);
+            Value result = appendWithBCI(invoke);
+            invoke.setExceptionEdge(handleException(null, bci()));
+            if (invoke.exceptionEdge() == null) {
+                TTY.println("no exception edge" + unwindHandler);
+            }
+            frameState.pushReturn(resultType, result);
+        }
+    }
+
+    private RiType getExactType(RiType staticType, Value receiver) {
+        RiType exact = staticType.exactType();
+        if (exact == null) {
+            exact = receiver.exactType();
+            if (exact == null) {
+                if (receiver.isConstant()) {
+                    exact = runtime.getTypeOf(receiver.asConstant());
+                }
+                if (exact == null) {
+                    RiType declared = receiver.declaredType();
+                    exact = declared == null || !declared.isResolved() ? null : declared.exactType();
+                }
+            }
+        }
+        return exact;
+    }
+
+    private void callRegisterFinalizer() {
+        // append a call to the finalizer registration
+        append(new RegisterFinalizer(frameState.loadLocal(0), graph));
+    }
+
+    private void genReturn(Value x) {
+        frameState.clearStack();
+        if (x != null) {
+            frameState.push(x.kind, x);
+        }
+        appendGoto(createTarget(returnBlock(bci()), frameState));
+    }
+
+    private void genMonitorEnter(Value x, int bci) {
+        int lockNumber = frameState.locksSize();
+        MonitorAddress lockAddress = null;
+        if (runtime.sizeOfBasicObjectLock() != 0) {
+            lockAddress = new MonitorAddress(lockNumber, graph);
+            append(lockAddress);
+        }
+        MonitorEnter monitorEnter = new MonitorEnter(x, lockAddress, lockNumber, graph);
+        appendWithBCI(monitorEnter);
+        frameState.lock(x);
+        if (bci == FixedNodeWithNext.SYNCHRONIZATION_ENTRY_BCI) {
+            monitorEnter.setStateAfter(frameState.create(0));
+        }
+    }
+
+    private void genMonitorExit(Value x) {
+        int lockNumber = frameState.locksSize() - 1;
+        if (lockNumber < 0) {
+            throw new CiBailout("monitor stack underflow");
+        }
+        MonitorAddress lockAddress = null;
+        if (runtime.sizeOfBasicObjectLock() != 0) {
+            lockAddress = new MonitorAddress(lockNumber, graph);
+            append(lockAddress);
+        }
+        appendWithBCI(new MonitorExit(x, lockAddress, lockNumber, graph));
+        frameState.unlock();
+    }
+
+    private void genJsr(int dest) {
+        throw new JSRNotSupportedBailout();
+    }
+
+    private void genRet(int localIndex) {
+        throw new JSRNotSupportedBailout();
+    }
+
+    private void genTableswitch() {
+        int bci = bci();
+        Value value = frameState.ipop();
+        BytecodeTableSwitch ts = new BytecodeTableSwitch(stream(), bci);
+        int max = ts.numberOfCases();
+        List<FixedNodeWithNext> list = new ArrayList<FixedNodeWithNext>(max + 1);
+        List<Integer> offsetList = new ArrayList<Integer>(max + 1);
+        for (int i = 0; i < max; i++) {
+            // add all successors to the successor list
+            int offset = ts.offsetAt(i);
+            list.add(null);
+            offsetList.add(offset);
+        }
+        int offset = ts.defaultOffset();
+        list.add(null);
+        offsetList.add(offset);
+        TableSwitch tableSwitch = new TableSwitch(value, list, ts.lowKey(), switchProbability(list.size(), bci), graph);
+        for (int i = 0; i < offsetList.size(); ++i) {
+            tableSwitch.setBlockSuccessor(i, createTargetAt(bci + offsetList.get(i), frameState));
+        }
+        append(tableSwitch);
+    }
+
+    private double[] switchProbability(int numberOfCases, int bci) {
+        double[] prob = method.switchProbability(bci);
+        if (prob != null) {
+            assert prob.length == numberOfCases;
+        } else {
+            if (GraalOptions.TraceProbability) {
+                TTY.println("Missing probability (switch) in " + method + " at bci " + bci);
+            }
+            prob = new double[numberOfCases];
+            for (int i = 0; i < numberOfCases; i++) {
+                prob[i] = 1.0d / numberOfCases;
+            }
+        }
+        return prob;
+    }
+
+    private void genLookupswitch() {
+        int bci = bci();
+        Value value = frameState.ipop();
+        BytecodeLookupSwitch ls = new BytecodeLookupSwitch(stream(), bci);
+        int max = ls.numberOfCases();
+        List<FixedNodeWithNext> list = new ArrayList<FixedNodeWithNext>(max + 1);
+        List<Integer> offsetList = new ArrayList<Integer>(max + 1);
+        int[] keys = new int[max];
+        for (int i = 0; i < max; i++) {
+            // add all successors to the successor list
+            int offset = ls.offsetAt(i);
+            list.add(null);
+            offsetList.add(offset);
+            keys[i] = ls.keyAt(i);
+        }
+        int offset = ls.defaultOffset();
+        list.add(null);
+        offsetList.add(offset);
+        LookupSwitch lookupSwitch = new LookupSwitch(value, list, keys, switchProbability(list.size(), bci), graph);
+        for (int i = 0; i < offsetList.size(); ++i) {
+            lookupSwitch.setBlockSuccessor(i, createTargetAt(bci + offsetList.get(i), frameState));
+        }
+        append(lookupSwitch);
+    }
+
+    private Constant appendConstant(CiConstant constant) {
+        return new Constant(constant, graph);
+    }
+
+    private Value append(FixedNode fixed) {
+        if (fixed instanceof Deoptimize && lastInstr.predecessors().size() > 0) {
+            Node cur = lastInstr;
+            Node prev = cur;
+            while (cur != cur.graph().start() && !(cur instanceof ControlSplit)) {
+                assert cur.predecessors().size() == 1;
+                prev = cur;
+                cur = cur.predecessors().get(0);
+                if (cur.predecessors().size() == 0) {
+                    break;
+                }
+
+                if (cur instanceof ExceptionObject) {
+                    break;
+                }
+            }
+
+            if (cur instanceof If) {
+                If ifNode = (If) cur;
+                if (ifNode.falseSuccessor() == prev) {
+                    FixedNode successor = ifNode.trueSuccessor();
+                    BooleanNode condition = ifNode.compare();
+                    FixedGuard fixedGuard = new FixedGuard(condition, graph);
+                    fixedGuard.setNext(successor);
+                    ifNode.replaceAndDelete(fixedGuard);
+                    lastInstr = null;
+                    return fixed;
+                }
+            } else if (prev != cur) {
+                prev.replaceAtPredecessors(fixed);
+                lastInstr = null;
+                return fixed;
+            }
+        }
+        lastInstr.setNext(fixed);
+        lastInstr = null;
+        return fixed;
+    }
+
+    private Value append(FixedNodeWithNext x) {
+        return appendWithBCI(x);
+    }
+
+    private Value append(Value v) {
+        return v;
+    }
+
+    private Value appendWithBCI(FixedNodeWithNext x) {
+        assert x.predecessors().size() == 0 : "instruction should not have been appended yet";
+        assert lastInstr.next() == null : "cannot append instruction to instruction which isn't end (" + lastInstr + "->" + lastInstr.next() + ")";
+        lastInstr.setNext(x);
+        lastInstr = x;
+        return x;
+    }
+
+    private FixedNode createTargetAt(int bci, FrameStateAccess stateAfter) {
+        return createTarget(blockFromBci[bci], stateAfter);
+    }
+
+    private FixedNode createTarget(Block block, FrameStateAccess stateAfter) {
+        assert block != null && stateAfter != null;
+        assert block.isLoopHeader || block.firstInstruction == null || block.firstInstruction.next() == null :
+            "non-loop block must be iterated after all its predecessors. startBci=" + block.startBci + ", " + block.getClass().getSimpleName() + ", " + block.firstInstruction.next();
+
+        if (block.isExceptionEntry) {
+            assert stateAfter.stackSize() == 1;
+        }
+
+        if (block.firstInstruction == null) {
+            if (block.isLoopHeader) {
+                LoopBegin loopBegin = new LoopBegin(graph);
+                loopBegin.addEnd(new EndNode(graph));
+                LoopEnd loopEnd = new LoopEnd(graph);
+                loopEnd.setLoopBegin(loopBegin);
+                Placeholder pBegin = new Placeholder(graph);
+                pBegin.setNext(loopBegin.forwardEdge());
+                Placeholder pEnd = new Placeholder(graph);
+                pEnd.setNext(loopEnd);
+                loopBegin.setStateAfter(stateAfter.duplicate(block.startBci));
+                block.firstInstruction = pBegin;
+            } else {
+                block.firstInstruction = new Placeholder(graph);
+            }
+        }
+        mergeOrClone(block, stateAfter);
+        addToWorkList(block);
+
+        FixedNode result = null;
+        if (block.isLoopHeader && isVisited(block)) {
+            result = (StateSplit) loopBegin(block).loopEnd().singlePredecessor();
+        } else {
+            result = block.firstInstruction;
+        }
+
+        assert result instanceof Merge || result instanceof Placeholder : result;
+
+        if (result instanceof Merge) {
+            if (result instanceof LoopBegin) {
+                result = ((LoopBegin) result).forwardEdge();
+            } else {
+                EndNode end = new EndNode(graph);
+                ((Merge) result).addEnd(end);
+                Placeholder p = new Placeholder(graph);
+                int bci = block.startBci;
+                if (block instanceof ExceptionBlock) {
+                    bci = ((ExceptionBlock) block).deoptBci;
+                }
+                p.setStateAfter(stateAfter.duplicate(bci));
+                p.setNext(end);
+                result = p;
+            }
+        }
+        assert !(result instanceof LoopBegin || result instanceof Merge);
+        return result;
+    }
+
+    private Value synchronizedObject(FrameStateAccess state, RiMethod target) {
+        if (isStatic(target.accessFlags())) {
+            Constant classConstant = new Constant(target.holder().getEncoding(Representation.JavaClass), graph);
+            return append(classConstant);
+        } else {
+            return state.localAt(0);
+        }
+    }
+
+    private void iterateAllBlocks() {
+        Block block;
+        while ((block = removeFromWorkList()) != null) {
+
+            // remove blocks that have no predecessors by the time it their bytecodes are parsed
+            if (block.firstInstruction == null) {
+                markVisited(block);
+                continue;
+            }
+
+            if (!isVisited(block)) {
+                markVisited(block);
+                // now parse the block
+                if (block.isLoopHeader) {
+                    LoopBegin begin = loopBegin(block);
+                    FrameState preLoopState = ((StateSplit) block.firstInstruction).stateAfter();
+                    assert preLoopState != null;
+                    FrameState duplicate = preLoopState.duplicate(preLoopState.bci);
+                    begin.setStateAfter(duplicate);
+                    insertLoopPhis(begin, duplicate);
+                    lastInstr = begin;
+                } else {
+                    lastInstr = block.firstInstruction;
+                }
+                frameState.initializeFrom(((StateSplit) lastInstr).stateAfter());
+                assert lastInstr.next() == null : "instructions already appended at block " + block.blockID;
+
+                if (block == returnBlock) {
+                    createReturnBlock(block);
+                } else if (block == unwindBlock) {
+                    createUnwindBlock(block);
+                } else if (block instanceof ExceptionBlock) {
+                    createExceptionDispatch((ExceptionBlock) block);
+                } else if (block instanceof DeoptBlock) {
+                    createDeoptBlock((DeoptBlock) block);
+                } else {
+                    frameState.setRethrowException(false);
+                    iterateBytecodesForBlock(block);
+                }
+            }
+        }
+        for (Block b : blocksVisited) {
+            if (b.isLoopHeader) {
+                LoopBegin begin = loopBegin(b);
+                LoopEnd loopEnd = begin.loopEnd();
+                StateSplit loopEndPred = (StateSplit) loopEnd.singlePredecessor();
+
+//              This can happen with degenerated loops like this one:
+//                for (;;) {
+//                    try {
+//                        break;
+//                    } catch (UnresolvedException iioe) {
+//                    }
+//                }
+                if (loopEndPred.stateAfter() != null) {
+                    //loopHeaderMerge.stateBefore().merge(begin, end.stateBefore());
+                    //assert loopHeaderMerge.equals(end.stateBefore());
+                    begin.stateAfter().merge(begin, loopEndPred.stateAfter());
+                } else {
+                    loopEndPred.delete();
+                    loopEnd.delete();
+                    Merge merge = new Merge(graph);
+                    merge.addEnd(begin.forwardEdge());
+                    merge.setNext(begin.next());
+                    merge.setStateAfter(begin.stateAfter());
+                    begin.replaceAndDelete(merge);
+                }
+            }
+        }
+    }
+
+    private static LoopBegin loopBegin(Block block) {
+        EndNode endNode = (EndNode) block.firstInstruction.next();
+        LoopBegin loopBegin = (LoopBegin) endNode.merge();
+        return loopBegin;
+    }
+
+    private void createDeoptBlock(DeoptBlock block) {
+        storeResultGraph = false;
+        append(new Deoptimize(DeoptAction.InvalidateReprofile, graph));
+    }
+
+    private void createUnwindBlock(Block block) {
+        if (Modifier.isSynchronized(method.accessFlags())) {
+            genMonitorExit(methodSynchronizedObject);
+        }
+        Unwind unwindNode = new Unwind(frameState.apop(), graph);
+        graph.setUnwind(unwindNode);
+        append(unwindNode);
+    }
+
+    private void createReturnBlock(Block block) {
+        if (method.isConstructor() && method.holder().superType() == null) {
+            callRegisterFinalizer();
+        }
+        CiKind returnKind = method.signature().returnKind().stackKind();
+        Value x = returnKind == CiKind.Void ? null : frameState.pop(returnKind);
+        assert frameState.stackSize() == 0;
+
+        if (Modifier.isSynchronized(method.accessFlags())) {
+            genMonitorExit(methodSynchronizedObject);
+        }
+        Return returnNode = new Return(x, graph);
+        graph.setReturn(returnNode);
+        append(returnNode);
+    }
+
+    private void createExceptionDispatch(ExceptionBlock block) {
+        if (block.handler == null) {
+            assert frameState.stackSize() == 1 : "only exception object expected on stack, actual size: " + frameState.stackSize();
+            createUnwindBlock(block);
+        } else {
+            assert frameState.stackSize() == 1 : frameState;
+
+            Block nextBlock = block.next == null ? unwindBlock(block.deoptBci) : block.next;
+
+
+            RiType catchType = block.handler.catchType();
+            Constant typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, catchType, catchType.isResolved());
+            if (typeInstruction != null) {
+                FixedNode catchSuccessor = createTarget(blockFromBci[block.handler.handlerBCI()], frameState);
+                FixedNode nextDispatch = createTarget(nextBlock, frameState);
+                Value exception = frameState.stackAt(0);
+                If ifNode = new If(new InstanceOf(typeInstruction, exception, false, graph), 0.5, graph);
+                append(ifNode);
+                ifNode.setTrueSuccessor(catchSuccessor);
+                ifNode.setFalseSuccessor(nextDispatch);
+            }
+        }
+    }
+
+    private void appendGoto(FixedNode target) {
+        if (lastInstr != null) {
+            lastInstr.setNext(target);
+        }
+    }
+
+    private void iterateBytecodesForBlock(Block block) {
+        assert frameState != null;
+
+        stream.setBCI(block.startBci);
+
+        int endBCI = stream.endBCI();
+
+        int bci = block.startBci;
+        while (bci < endBCI) {
+            Block nextBlock = blockFromBci[bci];
+            if (nextBlock != null && nextBlock != block) {
+                assert !nextBlock.isExceptionEntry;
+                // we fell through to the next block, add a goto and break
+                appendGoto(createTarget(nextBlock, frameState));
+                break;
+            }
+            // read the opcode
+            int opcode = stream.currentBC();
+            traceState();
+            traceInstruction(bci, opcode, bci == block.startBci);
+            processBytecode(bci, opcode);
+
+            if (lastInstr == null || IdentifyBlocksPhase.isBlockEnd(lastInstr) || lastInstr.next() != null) {
+                break;
+            }
+
+            stream.next();
+            bci = stream.currentBCI();
+            if (lastInstr instanceof StateSplit) {
+                StateSplit stateSplit = (StateSplit) lastInstr;
+                if (stateSplit.stateAfter() == null && stateSplit.needsStateAfter()) {
+                    stateSplit.setStateAfter(frameState.create(bci));
+                }
+            }
+        }
+    }
+
+    private void traceState() {
+        if (GraalOptions.TraceBytecodeParserLevel >= TRACELEVEL_STATE && !TTY.isSuppressed()) {
+            log.println(String.format("|   state [nr locals = %d, stack depth = %d, method = %s]", frameState.localsSize(), frameState.stackSize(), method));
+            for (int i = 0; i < frameState.localsSize(); ++i) {
+                Value value = frameState.localAt(i);
+                log.println(String.format("|   local[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind.javaName, value));
+            }
+            for (int i = 0; i < frameState.stackSize(); ++i) {
+                Value value = frameState.stackAt(i);
+                log.println(String.format("|   stack[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind.javaName, value));
+            }
+            for (int i = 0; i < frameState.locksSize(); ++i) {
+                Value value = frameState.lockAt(i);
+                log.println(String.format("|   lock[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind.javaName, value));
+            }
+        }
+    }
+
+    private void processBytecode(int bci, int opcode) {
+        int cpi;
+
+        // Checkstyle: stop
+        switch (opcode) {
+            case NOP            : /* nothing to do */ break;
+            case ACONST_NULL    : frameState.apush(appendConstant(CiConstant.NULL_OBJECT)); break;
+            case ICONST_M1      : frameState.ipush(appendConstant(CiConstant.INT_MINUS_1)); break;
+            case ICONST_0       : frameState.ipush(appendConstant(CiConstant.INT_0)); break;
+            case ICONST_1       : frameState.ipush(appendConstant(CiConstant.INT_1)); break;
+            case ICONST_2       : frameState.ipush(appendConstant(CiConstant.INT_2)); break;
+            case ICONST_3       : frameState.ipush(appendConstant(CiConstant.INT_3)); break;
+            case ICONST_4       : frameState.ipush(appendConstant(CiConstant.INT_4)); break;
+            case ICONST_5       : frameState.ipush(appendConstant(CiConstant.INT_5)); break;
+            case LCONST_0       : frameState.lpush(appendConstant(CiConstant.LONG_0)); break;
+            case LCONST_1       : frameState.lpush(appendConstant(CiConstant.LONG_1)); break;
+            case FCONST_0       : frameState.fpush(appendConstant(CiConstant.FLOAT_0)); break;
+            case FCONST_1       : frameState.fpush(appendConstant(CiConstant.FLOAT_1)); break;
+            case FCONST_2       : frameState.fpush(appendConstant(CiConstant.FLOAT_2)); break;
+            case DCONST_0       : frameState.dpush(appendConstant(CiConstant.DOUBLE_0)); break;
+            case DCONST_1       : frameState.dpush(appendConstant(CiConstant.DOUBLE_1)); break;
+            case BIPUSH         : frameState.ipush(appendConstant(CiConstant.forInt(stream.readByte()))); break;
+            case SIPUSH         : frameState.ipush(appendConstant(CiConstant.forInt(stream.readShort()))); break;
+            case LDC            : // fall through
+            case LDC_W          : // fall through
+            case LDC2_W         : genLoadConstant(stream.readCPI()); break;
+            case ILOAD          : loadLocal(stream.readLocalIndex(), CiKind.Int); break;
+            case LLOAD          : loadLocal(stream.readLocalIndex(), CiKind.Long); break;
+            case FLOAD          : loadLocal(stream.readLocalIndex(), CiKind.Float); break;
+            case DLOAD          : loadLocal(stream.readLocalIndex(), CiKind.Double); break;
+            case ALOAD          : loadLocal(stream.readLocalIndex(), CiKind.Object); break;
+            case ILOAD_0        : // fall through
+            case ILOAD_1        : // fall through
+            case ILOAD_2        : // fall through
+            case ILOAD_3        : loadLocal(opcode - ILOAD_0, CiKind.Int); break;
+            case LLOAD_0        : // fall through
+            case LLOAD_1        : // fall through
+            case LLOAD_2        : // fall through
+            case LLOAD_3        : loadLocal(opcode - LLOAD_0, CiKind.Long); break;
+            case FLOAD_0        : // fall through
+            case FLOAD_1        : // fall through
+            case FLOAD_2        : // fall through
+            case FLOAD_3        : loadLocal(opcode - FLOAD_0, CiKind.Float); break;
+            case DLOAD_0        : // fall through
+            case DLOAD_1        : // fall through
+            case DLOAD_2        : // fall through
+            case DLOAD_3        : loadLocal(opcode - DLOAD_0, CiKind.Double); break;
+            case ALOAD_0        : // fall through
+            case ALOAD_1        : // fall through
+            case ALOAD_2        : // fall through
+            case ALOAD_3        : loadLocal(opcode - ALOAD_0, CiKind.Object); break;
+            case IALOAD         : genLoadIndexed(CiKind.Int   ); break;
+            case LALOAD         : genLoadIndexed(CiKind.Long  ); break;
+            case FALOAD         : genLoadIndexed(CiKind.Float ); break;
+            case DALOAD         : genLoadIndexed(CiKind.Double); break;
+            case AALOAD         : genLoadIndexed(CiKind.Object); break;
+            case BALOAD         : genLoadIndexed(CiKind.Byte  ); break;
+            case CALOAD         : genLoadIndexed(CiKind.Char  ); break;
+            case SALOAD         : genLoadIndexed(CiKind.Short ); break;
+            case ISTORE         : storeLocal(CiKind.Int, stream.readLocalIndex()); break;
+            case LSTORE         : storeLocal(CiKind.Long, stream.readLocalIndex()); break;
+            case FSTORE         : storeLocal(CiKind.Float, stream.readLocalIndex()); break;
+            case DSTORE         : storeLocal(CiKind.Double, stream.readLocalIndex()); break;
+            case ASTORE         : storeLocal(CiKind.Object, stream.readLocalIndex()); break;
+            case ISTORE_0       : // fall through
+            case ISTORE_1       : // fall through
+            case ISTORE_2       : // fall through
+            case ISTORE_3       : storeLocal(CiKind.Int, opcode - ISTORE_0); break;
+            case LSTORE_0       : // fall through
+            case LSTORE_1       : // fall through
+            case LSTORE_2       : // fall through
+            case LSTORE_3       : storeLocal(CiKind.Long, opcode - LSTORE_0); break;
+            case FSTORE_0       : // fall through
+            case FSTORE_1       : // fall through
+            case FSTORE_2       : // fall through
+            case FSTORE_3       : storeLocal(CiKind.Float, opcode - FSTORE_0); break;
+            case DSTORE_0       : // fall through
+            case DSTORE_1       : // fall through
+            case DSTORE_2       : // fall through
+            case DSTORE_3       : storeLocal(CiKind.Double, opcode - DSTORE_0); break;
+            case ASTORE_0       : // fall through
+            case ASTORE_1       : // fall through
+            case ASTORE_2       : // fall through
+            case ASTORE_3       : storeLocal(CiKind.Object, opcode - ASTORE_0); break;
+            case IASTORE        : genStoreIndexed(CiKind.Int   ); break;
+            case LASTORE        : genStoreIndexed(CiKind.Long  ); break;
+            case FASTORE        : genStoreIndexed(CiKind.Float ); break;
+            case DASTORE        : genStoreIndexed(CiKind.Double); break;
+            case AASTORE        : genStoreIndexed(CiKind.Object); break;
+            case BASTORE        : genStoreIndexed(CiKind.Byte  ); break;
+            case CASTORE        : genStoreIndexed(CiKind.Char  ); break;
+            case SASTORE        : genStoreIndexed(CiKind.Short ); break;
+            case POP            : // fall through
+            case POP2           : // fall through
+            case DUP            : // fall through
+            case DUP_X1         : // fall through
+            case DUP_X2         : // fall through
+            case DUP2           : // fall through
+            case DUP2_X1        : // fall through
+            case DUP2_X2        : // fall through
+            case SWAP           : stackOp(opcode); break;
+            case IADD           : // fall through
+            case ISUB           : // fall through
+            case IMUL           : genArithmeticOp(CiKind.Int, opcode); break;
+            case IDIV           : // fall through
+            case IREM           : genArithmeticOp(CiKind.Int, opcode, true); break;
+            case LADD           : // fall through
+            case LSUB           : // fall through
+            case LMUL           : genArithmeticOp(CiKind.Long, opcode); break;
+            case LDIV           : // fall through
+            case LREM           : genArithmeticOp(CiKind.Long, opcode, true); break;
+            case FADD           : // fall through
+            case FSUB           : // fall through
+            case FMUL           : // fall through
+            case FDIV           : // fall through
+            case FREM           : genArithmeticOp(CiKind.Float, opcode); break;
+            case DADD           : // fall through
+            case DSUB           : // fall through
+            case DMUL           : // fall through
+            case DDIV           : // fall through
+            case DREM           : genArithmeticOp(CiKind.Double, opcode); break;
+            case INEG           : genNegateOp(CiKind.Int); break;
+            case LNEG           : genNegateOp(CiKind.Long); break;
+            case FNEG           : genNegateOp(CiKind.Float); break;
+            case DNEG           : genNegateOp(CiKind.Double); break;
+            case ISHL           : // fall through
+            case ISHR           : // fall through
+            case IUSHR          : genShiftOp(CiKind.Int, opcode); break;
+            case IAND           : // fall through
+            case IOR            : // fall through
+            case IXOR           : genLogicOp(CiKind.Int, opcode); break;
+            case LSHL           : // fall through
+            case LSHR           : // fall through
+            case LUSHR          : genShiftOp(CiKind.Long, opcode); break;
+            case LAND           : // fall through
+            case LOR            : // fall through
+            case LXOR           : genLogicOp(CiKind.Long, opcode); break;
+            case IINC           : genIncrement(); break;
+            case I2L            : genConvert(opcode, CiKind.Int   , CiKind.Long  ); break;
+            case I2F            : genConvert(opcode, CiKind.Int   , CiKind.Float ); break;
+            case I2D            : genConvert(opcode, CiKind.Int   , CiKind.Double); break;
+            case L2I            : genConvert(opcode, CiKind.Long  , CiKind.Int   ); break;
+            case L2F            : genConvert(opcode, CiKind.Long  , CiKind.Float ); break;
+            case L2D            : genConvert(opcode, CiKind.Long  , CiKind.Double); break;
+            case F2I            : genConvert(opcode, CiKind.Float , CiKind.Int   ); break;
+            case F2L            : genConvert(opcode, CiKind.Float , CiKind.Long  ); break;
+            case F2D            : genConvert(opcode, CiKind.Float , CiKind.Double); break;
+            case D2I            : genConvert(opcode, CiKind.Double, CiKind.Int   ); break;
+            case D2L            : genConvert(opcode, CiKind.Double, CiKind.Long  ); break;
+            case D2F            : genConvert(opcode, CiKind.Double, CiKind.Float ); break;
+            case I2B            : genConvert(opcode, CiKind.Int   , CiKind.Byte  ); break;
+            case I2C            : genConvert(opcode, CiKind.Int   , CiKind.Char  ); break;
+            case I2S            : genConvert(opcode, CiKind.Int   , CiKind.Short ); break;
+            case LCMP           : genCompareOp(CiKind.Long, opcode, CiKind.Int); break;
+            case FCMPL          : genCompareOp(CiKind.Float, opcode, CiKind.Int); break;
+            case FCMPG          : genCompareOp(CiKind.Float, opcode, CiKind.Int); break;
+            case DCMPL          : genCompareOp(CiKind.Double, opcode, CiKind.Int); break;
+            case DCMPG          : genCompareOp(CiKind.Double, opcode, CiKind.Int); break;
+            case IFEQ           : genIfZero(Condition.EQ); break;
+            case IFNE           : genIfZero(Condition.NE); break;
+            case IFLT           : genIfZero(Condition.LT); break;
+            case IFGE           : genIfZero(Condition.GE); break;
+            case IFGT           : genIfZero(Condition.GT); break;
+            case IFLE           : genIfZero(Condition.LE); break;
+            case IF_ICMPEQ      : genIfSame(CiKind.Int, Condition.EQ); break;
+            case IF_ICMPNE      : genIfSame(CiKind.Int, Condition.NE); break;
+            case IF_ICMPLT      : genIfSame(CiKind.Int, Condition.LT); break;
+            case IF_ICMPGE      : genIfSame(CiKind.Int, Condition.GE); break;
+            case IF_ICMPGT      : genIfSame(CiKind.Int, Condition.GT); break;
+            case IF_ICMPLE      : genIfSame(CiKind.Int, Condition.LE); break;
+            case IF_ACMPEQ      : genIfSame(frameState.peekKind(), Condition.EQ); break;
+            case IF_ACMPNE      : genIfSame(frameState.peekKind(), Condition.NE); break;
+            case GOTO           : genGoto(stream.currentBCI(), stream.readBranchDest()); break;
+            case JSR            : genJsr(stream.readBranchDest()); break;
+            case RET            : genRet(stream.readLocalIndex()); break;
+            case TABLESWITCH    : genTableswitch(); break;
+            case LOOKUPSWITCH   : genLookupswitch(); break;
+            case IRETURN        : genReturn(frameState.ipop()); break;
+            case LRETURN        : genReturn(frameState.lpop()); break;
+            case FRETURN        : genReturn(frameState.fpop()); break;
+            case DRETURN        : genReturn(frameState.dpop()); break;
+            case ARETURN        : genReturn(frameState.apop()); break;
+            case RETURN         : genReturn(null  ); break;
+            case GETSTATIC      : cpi = stream.readCPI(); genGetStatic(cpi, constantPool.lookupField(cpi, opcode)); break;
+            case PUTSTATIC      : cpi = stream.readCPI(); genPutStatic(cpi, constantPool.lookupField(cpi, opcode)); break;
+            case GETFIELD       : cpi = stream.readCPI(); genGetField(cpi, constantPool.lookupField(cpi, opcode)); break;
+            case PUTFIELD       : cpi = stream.readCPI(); genPutField(cpi, constantPool.lookupField(cpi, opcode)); break;
+            case INVOKEVIRTUAL  : cpi = stream.readCPI(); genInvokeVirtual(constantPool.lookupMethod(cpi, opcode), cpi, constantPool); break;
+            case INVOKESPECIAL  : cpi = stream.readCPI(); genInvokeSpecial(constantPool.lookupMethod(cpi, opcode), null, cpi, constantPool); break;
+            case INVOKESTATIC   : cpi = stream.readCPI(); genInvokeStatic(constantPool.lookupMethod(cpi, opcode), cpi, constantPool); break;
+            case INVOKEINTERFACE: cpi = stream.readCPI(); genInvokeInterface(constantPool.lookupMethod(cpi, opcode), cpi, constantPool); break;
+            case NEW            : genNewInstance(stream.readCPI()); break;
+            case NEWARRAY       : genNewTypeArray(stream.readLocalIndex()); break;
+            case ANEWARRAY      : genNewObjectArray(stream.readCPI()); break;
+            case ARRAYLENGTH    : genArrayLength(); break;
+            case ATHROW         : genThrow(stream.currentBCI()); break;
+            case CHECKCAST      : genCheckCast(); break;
+            case INSTANCEOF     : genInstanceOf(); break;
+            case MONITORENTER   : genMonitorEnter(frameState.apop(), stream.currentBCI()); break;
+            case MONITOREXIT    : genMonitorExit(frameState.apop()); break;
+            case MULTIANEWARRAY : genNewMultiArray(stream.readCPI()); break;
+            case IFNULL         : genIfNull(Condition.EQ); break;
+            case IFNONNULL      : genIfNull(Condition.NE); break;
+            case GOTO_W         : genGoto(stream.currentBCI(), stream.readFarBranchDest()); break;
+            case JSR_W          : genJsr(stream.readFarBranchDest()); break;
+            case BREAKPOINT:
+                throw new CiBailout("concurrent setting of breakpoint");
+            default:
+                throw new CiBailout("Unsupported opcode " + opcode + " (" + nameOf(opcode) + ") [bci=" + bci + "]");
+        }
+        // Checkstyle: resume
+    }
+
+    private void traceInstruction(int bci, int opcode, boolean blockStart) {
+        if (GraalOptions.TraceBytecodeParserLevel >= TRACELEVEL_INSTRUCTIONS && !TTY.isSuppressed()) {
+            StringBuilder sb = new StringBuilder(40);
+            sb.append(blockStart ? '+' : '|');
+            if (bci < 10) {
+                sb.append("  ");
+            } else if (bci < 100) {
+                sb.append(' ');
+            }
+            sb.append(bci).append(": ").append(Bytecodes.nameOf(opcode));
+            for (int i = bci + 1; i < stream.nextBCI(); ++i) {
+                sb.append(' ').append(stream.readUByte(i));
+            }
+            log.println(sb.toString());
+        }
+    }
+
+    private void genArrayLength() {
+        frameState.ipush(append(new ArrayLength(frameState.apop(), graph)));
+    }
+
+    /**
+     * Adds a block to the worklist, if it is not already in the worklist.
+     * This method will keep the worklist topologically stored (i.e. the lower
+     * DFNs are earlier in the list).
+     * @param block the block to add to the work list
+     */
+    private void addToWorkList(Block block) {
+        if (!isOnWorkList(block)) {
+            markOnWorkList(block);
+            sortIntoWorkList(block);
+        }
+    }
+
+    private void sortIntoWorkList(Block top) {
+        workList.offer(top);
+    }
+
+    /**
+     * Removes the next block from the worklist. The list is sorted topologically, so the
+     * block with the lowest depth first number in the list will be removed and returned.
+     * @return the next block from the worklist; {@code null} if there are no blocks
+     * in the worklist
+     */
+    private Block removeFromWorkList() {
+        return workList.poll();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,590 @@
+/*
+ * 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.max.graal.compiler.phases;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.graph.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.ir.Deoptimize.DeoptAction;
+import com.oracle.max.graal.compiler.value.*;
+import com.oracle.max.graal.extensions.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+
+public class InliningPhase extends Phase {
+    /*
+     * - Detect method which only call another method with some parameters set to constants: void foo(a) -> void foo(a, b) -> void foo(a, b, c) ...
+     *   These should not be taken into account when determining inlining depth.
+     */
+
+    public static final HashMap<RiMethod, Integer> methodCount = new HashMap<RiMethod, Integer>();
+
+    private static final int MAX_ITERATIONS = 1000;
+
+    private final GraalCompilation compilation;
+    private final IR ir;
+
+    private int inliningSize;
+    private final Collection<Invoke> hints;
+
+    public InliningPhase(GraalCompilation compilation, IR ir, Collection<Invoke> hints) {
+        this.compilation = compilation;
+        this.ir = ir;
+        this.hints = hints;
+    }
+
+    private Queue<Invoke> newInvokes = new ArrayDeque<Invoke>();
+    private CompilerGraph graph;
+
+    @Override
+    protected void run(Graph graph) {
+        this.graph = (CompilerGraph) graph;
+
+        float ratio = GraalOptions.MaximumInlineRatio;
+        inliningSize = compilation.method.codeSize();
+
+        if (hints != null) {
+            newInvokes.addAll(hints);
+        } else {
+            for (Invoke invoke : graph.getNodes(Invoke.class)) {
+                newInvokes.add(invoke);
+            }
+        }
+
+        for (int iterations = 0; iterations < MAX_ITERATIONS; iterations++) {
+            Queue<Invoke> queue = newInvokes;
+            newInvokes = new ArrayDeque<Invoke>();
+            for (Invoke invoke : queue) {
+                if (!invoke.isDeleted()) {
+                    RiMethod code = inlineInvoke(invoke, iterations, ratio);
+                    if (code != null) {
+                        if (graph.getNodeCount() > GraalOptions.MaximumInstructionCount) {
+                            break;
+                        }
+
+                        inlineMethod(invoke, code);
+                        if (GraalOptions.TraceInlining) {
+                            if (methodCount.get(code) == null) {
+                                methodCount.put(code, 1);
+                            } else {
+                                methodCount.put(code, methodCount.get(code) + 1);
+                            }
+                        }
+                    }
+                }
+            }
+            if (newInvokes.isEmpty()) {
+                break;
+            }
+
+//            new DeadCodeEliminationPhase().apply(graph);
+
+            ratio *= GraalOptions.MaximumInlineRatio;
+        }
+
+        if (GraalOptions.TraceInlining) {
+            int inlined = 0;
+            int duplicate = 0;
+            for (Map.Entry<RiMethod, Integer> entry : methodCount.entrySet()) {
+                inlined += entry.getValue();
+                duplicate += entry.getValue() - 1;
+            }
+            if (inlined > 0) {
+                TTY.println("overhead: %d (%5.3f %%)", duplicate, duplicate * 100.0 / inlined);
+            }
+        }
+    }
+
+    private RiMethod inlineInvoke(Invoke invoke, int iterations, float ratio) {
+        RiMethod parent = invoke.stateAfter().method();
+        RiTypeProfile profile = parent.typeProfile(invoke.bci);
+        if (GraalOptions.Intrinsify) {
+            if (GraalOptions.Extend && intrinsicGraph(parent, invoke.bci, invoke.target, invoke.arguments()) != null) {
+                return invoke.target;
+            }
+            if (compilation.runtime.intrinsicGraph(parent, invoke.bci, invoke.target, invoke.arguments()) != null) {
+                // Always intrinsify.
+                return invoke.target;
+            }
+        }
+        if (!checkInvokeConditions(invoke)) {
+            return null;
+        }
+        if (invoke.opcode() == Bytecodes.INVOKESPECIAL || invoke.target.canBeStaticallyBound()) {
+            if (checkTargetConditions(invoke.target, iterations) && checkSizeConditions(parent, iterations, invoke.target, invoke, profile, ratio)) {
+                return invoke.target;
+            }
+            return null;
+        }
+        if (invoke.receiver().exactType() != null) {
+            RiType exact = invoke.receiver().exactType();
+            assert exact.isSubtypeOf(invoke.target().holder()) : exact + " subtype of " + invoke.target().holder();
+            RiMethod resolved = exact.resolveMethodImpl(invoke.target());
+            if (checkTargetConditions(resolved, iterations) && checkSizeConditions(parent, iterations, resolved, invoke, profile, ratio)) {
+                return resolved;
+            }
+            return null;
+        }
+        RiType holder = invoke.target().holder();
+
+        if (invoke.receiver().declaredType() != null) {
+            RiType declared = invoke.receiver().declaredType();
+            // the invoke target might be more specific than the holder (happens after inlining: locals lose their declared type...)
+            // TODO (ls) fix this
+            if (declared.isResolved() && declared.isSubtypeOf(invoke.target().holder())) {
+                holder = declared;
+            }
+        }
+
+        RiMethod concrete = holder.uniqueConcreteMethod(invoke.target);
+        if (concrete != null) {
+            if (checkTargetConditions(concrete, iterations) && checkSizeConditions(parent, iterations, concrete, invoke, profile, ratio)) {
+                if (GraalOptions.TraceInlining) {
+                    String targetName = CiUtil.format("%H.%n(%p):%r", invoke.target, false);
+                    String concreteName = CiUtil.format("%H.%n(%p):%r", concrete, false);
+                    TTY.println("recording concrete method assumption: %s -> %s", targetName, concreteName);
+                }
+                graph.assumptions().recordConcreteMethod(invoke.target, concrete);
+                return concrete;
+            }
+            return null;
+        }
+        if (profile != null && profile.probabilities != null && profile.probabilities.length > 0 && profile.morphism == 1) {
+            if (GraalOptions.InlineWithTypeCheck) {
+                // type check and inlining...
+                concrete = profile.types[0].resolveMethodImpl(invoke.target);
+                if (concrete != null && checkTargetConditions(concrete, iterations) && checkSizeConditions(parent, iterations, concrete, invoke, profile, ratio)) {
+                    IsType isType = new IsType(invoke.receiver(), profile.types[0], compilation.graph);
+                    FixedGuard guard = new FixedGuard(isType, graph);
+                    assert invoke.predecessors().size() == 1;
+                    invoke.predecessors().get(0).successors().replace(invoke, guard);
+                    guard.setNext(invoke);
+
+                    if (GraalOptions.TraceInlining) {
+                        TTY.println("inlining with type check, type probability: %5.3f", profile.probabilities[0]);
+                    }
+                    return concrete;
+                }
+                return null;
+            } else {
+                if (GraalOptions.TraceInlining) {
+                    TTY.println("not inlining %s because GraalOptions.InlineWithTypeCheck == false", methodName(invoke.target, invoke));
+                }
+                return null;
+            }
+        } else {
+            if (GraalOptions.TraceInlining) {
+                TTY.println("not inlining %s because no monomorphic receiver could be found", methodName(invoke.target, invoke));
+            }
+            return null;
+        }
+    }
+
+    private String methodName(RiMethod method) {
+        return CiUtil.format("%H.%n(%p):%r", method, false) + " (" + method.codeSize() + " bytes)";
+    }
+
+    private String methodName(RiMethod method, Invoke invoke) {
+        if (invoke != null) {
+            RiMethod parent = invoke.stateAfter().method();
+            return parent.name() + "@" + invoke.bci + ": " + CiUtil.format("%H.%n(%p):%r", method, false) + " (" + method.codeSize() + " bytes)";
+        } else {
+            return CiUtil.format("%H.%n(%p):%r", method, false) + " (" + method.codeSize() + " bytes)";
+        }
+    }
+
+    private boolean checkInvokeConditions(Invoke invoke) {
+        if (!invoke.canInline()) {
+            if (GraalOptions.TraceInlining) {
+                TTY.println("not inlining %s because the invoke is manually set to be non-inlinable", methodName(invoke.target, invoke));
+            }
+            return false;
+        }
+        if (invoke.stateAfter() == null) {
+            if (GraalOptions.TraceInlining) {
+                TTY.println("not inlining %s because the invoke has no after state", methodName(invoke.target, invoke));
+            }
+            return false;
+        }
+        if (invoke.stateAfter().locksSize() > 0) {
+            if (GraalOptions.TraceInlining) {
+                TTY.println("not inlining %s because of locks", methodName(invoke.target, invoke));
+            }
+            return false;
+        }
+        if (!invoke.target.isResolved()) {
+            if (GraalOptions.TraceInlining) {
+                TTY.println("not inlining %s because the invoke target is unresolved", methodName(invoke.target, invoke));
+            }
+            return false;
+        }
+        if (invoke.predecessors().size() == 0) {
+            if (GraalOptions.TraceInlining) {
+                TTY.println("not inlining %s because the invoke is dead code", methodName(invoke.target, invoke));
+            }
+            return false;
+        }
+        if (invoke.stateAfter() == null) {
+            if (GraalOptions.TraceInlining) {
+                TTY.println("not inlining %s because of missing frame state", methodName(invoke.target, invoke));
+            }
+        }
+        return true;
+    }
+
+    private boolean checkTargetConditions(RiMethod method, int iterations) {
+        if (!method.isResolved()) {
+            if (GraalOptions.TraceInlining) {
+                TTY.println("not inlining %s because it is unresolved", methodName(method));
+            }
+            return false;
+        }
+        if (Modifier.isNative(method.accessFlags())) {
+            if (GraalOptions.TraceInlining) {
+                TTY.println("not inlining %s because it is a native method", methodName(method));
+            }
+            return false;
+        }
+        if (Modifier.isAbstract(method.accessFlags())) {
+            if (GraalOptions.TraceInlining) {
+                TTY.println("not inlining %s because it is an abstract method", methodName(method));
+            }
+            return false;
+        }
+        if (!method.holder().isInitialized()) {
+            if (GraalOptions.TraceInlining) {
+                TTY.println("not inlining %s because of non-initialized class", methodName(method));
+            }
+            return false;
+        }
+        return true;
+    }
+
+    private boolean checkStaticSizeConditions(RiMethod method, Invoke invoke) {
+        int maximumSize = GraalOptions.MaximumInlineSize;
+        if (hints != null && hints.contains(invoke)) {
+            maximumSize = GraalOptions.MaximumFreqInlineSize;
+        }
+        if (method.codeSize() > maximumSize) {
+            if (GraalOptions.TraceInlining) {
+                TTY.println("not inlining %s because of code size (size: %d, max size: %d)", methodName(method, invoke), method.codeSize(), GraalOptions.MaximumInlineSize);
+            }
+            return false;
+        }
+        return true;
+    }
+
+    private boolean checkSizeConditions(RiMethod caller, int iterations, RiMethod method, Invoke invoke, RiTypeProfile profile, float adjustedRatio) {
+        int maximumSize = GraalOptions.MaximumTrivialSize;
+        double ratio = 0;
+        if (profile != null && profile.count > 0) {
+            RiMethod parent = invoke.stateAfter().method();
+            if (GraalOptions.ProbabilityAnalysis) {
+                ratio = invoke.probability();
+            } else {
+                ratio = profile.count / (float) parent.invocationCount();
+            }
+            if (ratio >= GraalOptions.FreqInlineRatio) {
+                maximumSize = GraalOptions.MaximumFreqInlineSize;
+            } else if (ratio >= 1 * (1 - adjustedRatio)) {
+                maximumSize = GraalOptions.MaximumInlineSize;
+            }
+        }
+        if (hints != null && hints.contains(invoke)) {
+            maximumSize = GraalOptions.MaximumFreqInlineSize;
+        }
+        if (method.codeSize() > maximumSize || iterations >= GraalOptions.MaximumInlineLevel || (method == compilation.method && iterations > GraalOptions.MaximumRecursiveInlineLevel)) {
+            if (GraalOptions.TraceInlining) {
+                TTY.println("not inlining %s because of code size (size: %d, max size: %d, ratio %5.3f, %s) or inling level", methodName(method, invoke), method.codeSize(), maximumSize, ratio, profile);
+            }
+            if (GraalOptions.Extend) {
+                boolean newResult = overrideInliningDecision(iterations, caller, invoke.bci, method, false);
+                if (GraalOptions.TraceInlining && newResult) {
+                    TTY.println("overridden inlining decision");
+                }
+                return newResult;
+            }
+            return false;
+        }
+        if (GraalOptions.TraceInlining) {
+            TTY.println("inlining %s (size: %d, max size: %d, ratio %5.3f, %s)", methodName(method, invoke), method.codeSize(), maximumSize, ratio, profile);
+        }
+        if (GraalOptions.Extend) {
+            boolean newResult = overrideInliningDecision(iterations, caller, invoke.bci, method, true);
+            if (GraalOptions.TraceInlining && !newResult) {
+                TTY.println("overridden inlining decision");
+            }
+            return newResult;
+        }
+        return true;
+    }
+
+    public static ThreadLocal<ServiceLoader<InliningGuide>> guideLoader = new ThreadLocal<ServiceLoader<InliningGuide>>();
+
+    private boolean overrideInliningDecision(int iteration, RiMethod caller, int bci, RiMethod target, boolean previousDecision) {
+        ServiceLoader<InliningGuide> serviceLoader = guideLoader.get();
+        if (serviceLoader == null) {
+            serviceLoader = ServiceLoader.load(InliningGuide.class);
+            guideLoader.set(serviceLoader);
+        }
+
+        boolean neverInline = false;
+        boolean alwaysInline = false;
+        for (InliningGuide guide : serviceLoader) {
+            InliningHint hint = guide.getHint(iteration, caller, bci, target);
+
+            if (hint == InliningHint.ALWAYS) {
+                alwaysInline = true;
+            } else if (hint == InliningHint.NEVER) {
+                neverInline = true;
+            }
+        }
+
+        if (neverInline && alwaysInline) {
+            if (GraalOptions.TraceInlining) {
+                TTY.println("conflicting inlining hints");
+            }
+        } else if (neverInline) {
+            return false;
+        } else if (alwaysInline) {
+            return true;
+        }
+        return previousDecision;
+    }
+
+
+    public static ThreadLocal<ServiceLoader<Intrinsifier>> intrinsicLoader = new ThreadLocal<ServiceLoader<Intrinsifier>>();
+
+    private Graph intrinsicGraph(RiMethod parent, int bci, RiMethod target, List<Value> arguments) {
+        ServiceLoader<Intrinsifier> serviceLoader = intrinsicLoader.get();
+        if (serviceLoader == null) {
+            serviceLoader = ServiceLoader.load(Intrinsifier.class);
+            intrinsicLoader.set(serviceLoader);
+        }
+
+        for (Intrinsifier intrinsifier : serviceLoader) {
+            Graph result = intrinsifier.intrinsicGraph(compilation.runtime, parent, bci, target, arguments);
+            if (result != null) {
+                return result;
+            }
+        }
+        return null;
+    }
+
+    private void inlineMethod(Invoke invoke, RiMethod method) {
+        RiMethod parent = invoke.stateAfter().method();
+        FrameState stateAfter = invoke.stateAfter();
+        FixedNode exceptionEdge = invoke.exceptionEdge();
+        if (exceptionEdge instanceof Placeholder) {
+            exceptionEdge = ((Placeholder) exceptionEdge).next();
+        }
+
+        boolean withReceiver = !invoke.isStatic();
+
+        int argumentCount = method.signature().argumentCount(false);
+        Value[] parameters = new Value[argumentCount + (withReceiver ? 1 : 0)];
+        int slot = withReceiver ? 1 : 0;
+        int param = withReceiver ? 1 : 0;
+        for (int i = 0; i < argumentCount; i++) {
+            parameters[param++] = invoke.arguments().get(slot);
+            slot += method.signature().argumentKindAt(i).sizeInSlots();
+        }
+        if (withReceiver) {
+            parameters[0] = invoke.arguments().get(0);
+        }
+
+        CompilerGraph graph = null;
+        if (GraalOptions.Intrinsify) {
+            if (GraalOptions.Extend) {
+                graph = (CompilerGraph) intrinsicGraph(parent, invoke.bci, method, invoke.arguments());
+            }
+            if (graph == null) {
+                graph = (CompilerGraph) compilation.runtime.intrinsicGraph(parent, invoke.bci, method, invoke.arguments());
+            }
+        }
+        if (graph != null) {
+            if (GraalOptions.TraceInlining) {
+                TTY.println("Using intrinsic graph");
+            }
+        } else {
+            graph = GraphBuilderPhase.cachedGraphs.get(method);
+        }
+
+        if (graph != null) {
+            if (GraalOptions.TraceInlining) {
+                TTY.println("Reusing graph for %s", methodName(method, invoke));
+            }
+        } else {
+            if (GraalOptions.TraceInlining) {
+                TTY.println("Building graph for %s, locals: %d, stack: %d", methodName(method, invoke), method.maxLocals(), method.maxStackSize());
+            }
+            graph = new CompilerGraph(null);
+            new GraphBuilderPhase(compilation, method, true).apply(graph, true, false);
+            if (GraalOptions.ProbabilityAnalysis) {
+                new DeadCodeEliminationPhase().apply(graph, true, false);
+                new ComputeProbabilityPhase().apply(graph, true, false);
+            }
+        }
+
+        invoke.inputs().clearAll();
+
+        HashMap<Node, Node> replacements = new HashMap<Node, Node>();
+        ArrayList<Node> nodes = new ArrayList<Node>();
+        ArrayList<Node> frameStates = new ArrayList<Node>();
+        Return returnNode = null;
+        Unwind unwindNode = null;
+        StartNode startNode = graph.start();
+        for (Node node : graph.getNodes()) {
+            if (node instanceof StartNode) {
+                assert startNode == node;
+            } else if (node instanceof Local) {
+                replacements.put(node, parameters[((Local) node).index()]);
+            } else {
+                nodes.add(node);
+                if (node instanceof Return) {
+                    returnNode = (Return) node;
+                } else if (node instanceof Unwind) {
+                    unwindNode = (Unwind) node;
+                } else if (node instanceof FrameState) {
+                    frameStates.add(node);
+                }
+            }
+        }
+
+        if (GraalOptions.TraceInlining) {
+            TTY.println("inlining %s: %d frame states, %d nodes", methodName(method), frameStates.size(), nodes.size());
+        }
+
+        assert invoke.successors().get(0) != null : invoke;
+        assert invoke.predecessors().size() == 1 : "size: " + invoke.predecessors().size();
+        FixedNodeWithNext pred;
+        if (withReceiver) {
+            pred = new FixedGuard(new IsNonNull(parameters[0], compilation.graph), compilation.graph);
+        } else {
+            pred = new Placeholder(compilation.graph);
+        }
+        invoke.replaceAtPredecessors(pred);
+        replacements.put(startNode, pred);
+
+        Map<Node, Node> duplicates = compilation.graph.addDuplicate(nodes, replacements);
+
+        FrameState stateBefore = null;
+        double invokeProbability = invoke.probability();
+        for (Node node : duplicates.values()) {
+            if (GraalOptions.ProbabilityAnalysis) {
+                if (node instanceof FixedNode) {
+                    FixedNode fixed = (FixedNode) node;
+                    fixed.setProbability(fixed.probability() * invokeProbability);
+                }
+            }
+            if (node instanceof Invoke && ((Invoke) node).canInline()) {
+                newInvokes.add((Invoke) node);
+            } else if (node instanceof FrameState) {
+                FrameState frameState = (FrameState) node;
+                if (frameState.bci == FrameState.BEFORE_BCI) {
+                    if (stateBefore == null) {
+                        stateBefore = stateAfter.duplicateModified(invoke.bci, false, invoke.kind, parameters);
+                    }
+                    frameState.replaceAndDelete(stateBefore);
+                } else if (frameState.bci == FrameState.AFTER_BCI) {
+                    frameState.replaceAndDelete(stateAfter);
+                }
+            }
+        }
+
+        int monitorIndexDelta = stateAfter.locksSize();
+        if (monitorIndexDelta > 0) {
+            for (Map.Entry<Node, Node> entry : duplicates.entrySet()) {
+                if (entry.getValue() instanceof MonitorAddress) {
+                    MonitorAddress address = (MonitorAddress) entry.getValue();
+                    address.setMonitorIndex(address.monitorIndex() + monitorIndexDelta);
+                }
+            }
+        }
+
+        if (pred instanceof Placeholder) {
+            pred.replaceAndDelete(((Placeholder) pred).next());
+        }
+
+        if (returnNode != null) {
+            List<Node> usages = new ArrayList<Node>(invoke.usages());
+            for (Node usage : usages) {
+                if (returnNode.result() instanceof Local) {
+                    usage.inputs().replace(invoke, replacements.get(returnNode.result()));
+                } else {
+                    usage.inputs().replace(invoke, duplicates.get(returnNode.result()));
+                }
+            }
+            Node returnDuplicate = duplicates.get(returnNode);
+            returnDuplicate.inputs().clearAll();
+            Node n = invoke.next();
+            invoke.setNext(null);
+            returnDuplicate.replaceAndDelete(n);
+        }
+
+        if (exceptionEdge != null) {
+            if (unwindNode != null) {
+                assert unwindNode.predecessors().size() == 1;
+                assert exceptionEdge.successors().size() == 1;
+                ExceptionObject obj = (ExceptionObject) exceptionEdge;
+
+                Unwind unwindDuplicate = (Unwind) duplicates.get(unwindNode);
+                List<Node> usages = new ArrayList<Node>(obj.usages());
+                for (Node usage : usages) {
+                    usage.inputs().replace(obj, unwindDuplicate.exception());
+                }
+                unwindDuplicate.inputs().clearAll();
+                Node n = obj.next();
+                obj.setNext(null);
+                unwindDuplicate.replaceAndDelete(n);
+            }
+        } else {
+            if (unwindNode != null) {
+                Unwind unwindDuplicate = (Unwind) duplicates.get(unwindNode);
+                unwindDuplicate.replaceAndDelete(new Deoptimize(DeoptAction.InvalidateRecompile, compilation.graph));
+            }
+        }
+
+        // adjust all frame states that were copied
+        if (frameStates.size() > 0) {
+            FrameState outerFrameState = stateAfter.duplicateModified(invoke.bci, stateAfter.rethrowException(), invoke.kind);
+            for (Node node : frameStates) {
+                FrameState frameState = (FrameState) duplicates.get(node);
+                if (!frameState.isDeleted()) {
+                    frameState.setOuterFrameState(outerFrameState);
+                }
+            }
+        }
+
+        if (GraalOptions.TraceInlining) {
+            ir.printGraph("After inlining " + CiUtil.format("%H.%n(%p):%r", method, false), compilation.graph);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoopPhase.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,198 @@
+/*
+ * 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.max.graal.compiler.phases;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.ir.Phi.PhiType;
+import com.oracle.max.graal.compiler.observer.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.compiler.util.LoopUtil.Loop;
+import com.oracle.max.graal.compiler.value.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public class LoopPhase extends Phase {
+
+    @Override
+    protected void run(Graph graph) {
+        List<Loop> loops = LoopUtil.computeLoops(graph);
+
+        if (GraalOptions.LoopPeeling || GraalOptions.LoopInversion) {
+            for (Loop loop : loops) {
+                boolean hasBadExit = false;
+                for (Node exit : loop.exits()) {
+                    if (!(exit instanceof StateSplit) || ((StateSplit) exit).stateAfter() == null) {
+                        // TODO (gd) can not do loop peeling if an exit has no state. see LoopUtil.findNearestMergableExitPoint
+                        hasBadExit = true;
+                        break;
+                    }
+                }
+                if (hasBadExit) {
+                    continue;
+                }
+                boolean canInvert = false;
+                if (GraalOptions.LoopInversion  && loop.loopBegin().next() instanceof If) {
+                    If ifNode = (If) loop.loopBegin().next();
+                    if (loop.exits().isMarked(ifNode.trueSuccessor()) || loop.exits().isMarked(ifNode.falseSuccessor())) {
+                        canInvert = true;
+                    }
+                }
+                if (canInvert) {
+                    LoopUtil.inverseLoop(loop, (If) loop.loopBegin().next());
+                } else if (GraalOptions.LoopPeeling) {
+                    GraalCompilation compilation = GraalCompilation.compilation();
+                    if (compilation.compiler.isObserved()) {
+                        Map<String, Object> debug = new HashMap<String, Object>();
+                        debug.put("loopExits", loop.exits());
+                        debug.put("inOrBefore", loop.inOrBefore());
+                        debug.put("inOrAfter", loop.inOrAfter());
+                        debug.put("nodes", loop.nodes());
+                        compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "Loop #" + loop.loopBegin().id(), graph, true, false, debug));
+                    }
+                    LoopUtil.peelLoop(loop);
+                }
+            }
+        }
+
+        /*
+        for (Loop loop : loops) {
+            doLoopCounters(loop);
+        }*/
+    }
+
+    private void doLoopCounters(Loop loop) {
+        LoopBegin loopBegin = loop.loopBegin();
+        List<LoopCounter> counters = findLoopCounters(loopBegin, loop.nodes());
+        mergeLoopCounters(counters, loopBegin);
+    }
+
+    private void mergeLoopCounters(List<LoopCounter> counters, LoopBegin loopBegin) {
+        Graph graph = loopBegin.graph();
+        FrameState stateAfter = loopBegin.stateAfter();
+        LoopCounter[] acounters = counters.toArray(new LoopCounter[counters.size()]);
+        for (int i = 0; i < acounters.length; i++) {
+            LoopCounter c1 = acounters[i];
+            if (c1 == null) {
+                continue;
+            }
+            for (int j = i + 1; j < acounters.length; j++) {
+                LoopCounter c2 = acounters[j];
+                if (c2 != null && c1.stride().valueEqual(c2.stride())) {
+                    boolean c1InCompare = Util.filter(c1.usages(), Compare.class).size() > 0;
+                    boolean c2inCompare = Util.filter(c2.usages(), Compare.class).size() > 0;
+                    if (c2inCompare && !c1InCompare) {
+                        c1 = acounters[j];
+                        c2 = acounters[i];
+                        acounters[i] = c2;
+                        acounters[j] = c1;
+                    }
+                    boolean c2InFramestate = stateAfter != null ? stateAfter.inputs().contains(c2) : false;
+                    acounters[j] = null;
+                    CiKind kind = c1.kind;
+                    if (c2InFramestate) {
+                        IntegerSub sub = new IntegerSub(kind, c2.init(), c1.init(), graph);
+                        IntegerAdd addStride = new IntegerAdd(kind, sub, c1.stride(), graph);
+                        IntegerAdd add = new IntegerAdd(kind, c1, addStride, graph);
+                        Phi phi = new Phi(kind, loopBegin, PhiType.Value, graph); // (gd) assumes order on loopBegin preds - works in collab with graph builder
+                        phi.addInput(c2.init());
+                        phi.addInput(add);
+                        c2.replaceAndDelete(phi);
+                    } else {
+                        IntegerSub sub = new IntegerSub(kind, c2.init(), c1.init(), graph);
+                        IntegerAdd add = new IntegerAdd(kind, c1, sub, graph);
+                        c2.replaceAndDelete(add);
+                    }
+                }
+            }
+        }
+    }
+
+    private List<LoopCounter> findLoopCounters(LoopBegin loopBegin, NodeBitMap loopNodes) {
+        LoopEnd loopEnd = loopBegin.loopEnd();
+        FrameState loopEndState = null;
+        Node loopEndPred = loopEnd.singlePredecessor();
+        if (loopEndPred instanceof Merge) {
+            loopEndState = ((Merge) loopEndPred).stateAfter();
+        }
+        List<Node> usages = new ArrayList<Node>(loopBegin.usages());
+        List<LoopCounter> counters = new LinkedList<LoopCounter>();
+        for (Node usage : usages) {
+            if (usage instanceof Phi) {
+                Phi phi = (Phi) usage;
+                if (phi.valueCount() == 2) {
+                    Value backEdge = phi.valueAt(1);
+                    Value init = phi.valueAt(0);
+                    if (loopNodes.isNew(init) || loopNodes.isNew(backEdge)) {
+                        continue;
+                    }
+                    if (loopNodes.isMarked(init)) {
+                        // try to reverse init/backEdge order
+                        Value tmp = backEdge;
+                        backEdge = init;
+                        init = tmp;
+                    }
+                    Value stride = null;
+                    boolean useCounterAfterAdd = false;
+                    if (!loopNodes.isMarked(init) && backEdge instanceof IntegerAdd && loopNodes.isMarked(backEdge)) {
+                        IntegerAdd add = (IntegerAdd) backEdge;
+                        int addUsageCount = 0;
+                        for (Node u : add.usages()) {
+                            if (u != loopEndState && u != phi) {
+                                addUsageCount++;
+                            }
+                        }
+                        if (add.x() == phi) {
+                            stride = add.y();
+                        } else if (add.y() == phi) {
+                            stride = add.x();
+                        }
+                        if (addUsageCount > 0) {
+                            useCounterAfterAdd = true;
+                        }
+                    }
+                    if (stride != null && loopNodes.isNotNewNotMarked(stride)) {
+                        Graph graph = loopBegin.graph();
+                        LoopCounter counter = new LoopCounter(init.kind, init, stride, loopBegin, graph);
+                        counters.add(counter);
+                        phi.replaceAndDelete(counter);
+                        if (loopEndState != null) {
+                            loopEndState.inputs().replace(backEdge, counter);
+                        }
+                        if (useCounterAfterAdd) {
+                            /*IntegerAdd otherInit = new IntegerAdd(init.kind, init, stride, graph); // would be nice to canonicalize
+                            LoopCounter otherCounter = new LoopCounter(init.kind, otherInit, stride, loopBegin, graph);
+                            backEdge.replace(otherCounter);*/
+                        } else {
+                            backEdge.delete();
+                        }
+                    }
+                }
+            }
+        }
+        return counters;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoweringPhase.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,98 @@
+/*
+ * 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.max.graal.compiler.phases;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.schedule.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+public class LoweringPhase extends Phase {
+
+    public static final LoweringOp DELEGATE_TO_RUNTIME = new LoweringOp() {
+        @Override
+        public void lower(Node n, CiLoweringTool tool) {
+            tool.getRuntime().lower(n, tool);
+        }
+    };
+
+    private final RiRuntime runtime;
+
+    public LoweringPhase(RiRuntime runtime) {
+        this.runtime = runtime;
+    }
+
+    @Override
+    protected void run(final Graph graph) {
+        final IdentifyBlocksPhase s = new IdentifyBlocksPhase(false);
+        s.apply(graph);
+
+        List<Block> blocks = s.getBlocks();
+        for (final Block b : blocks) {
+            process(b);
+        }
+    }
+
+    private void process(final Block b) {
+
+        final Node anchor = b.javaBlock().createAnchor();
+        final CiLoweringTool loweringTool = new CiLoweringTool() {
+
+            @Override
+            public Node getGuardAnchor() {
+                return anchor;
+            }
+
+            @Override
+            public RiRuntime getRuntime() {
+                return runtime;
+            }
+
+            @Override
+            public Node createGuard(Node condition) {
+                Anchor anchor = (Anchor) getGuardAnchor();
+                GuardNode newGuard = new GuardNode((BooleanNode) condition, anchor.graph());
+                newGuard.setAnchor(anchor);
+                return newGuard;
+            }
+        };
+
+
+        // Lower the instructions of this block.
+        for (final Node n : b.getInstructions()) {
+            if (n instanceof FixedNode) {
+                LoweringOp op = n.lookup(LoweringOp.class);
+                if (op != null) {
+                    op.lower(n, loweringTool);
+                }
+            }
+        }
+    }
+
+    public interface LoweringOp extends Op {
+        void lower(Node n, CiLoweringTool tool);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/MemoryPhase.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,326 @@
+/*
+ * 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.max.graal.compiler.phases;
+
+import java.util.*;
+import java.util.Map.Entry;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.ir.Phi.*;
+import com.oracle.max.graal.compiler.schedule.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+public class MemoryPhase extends Phase {
+
+    public static class MemoryMap {
+
+        private final Block block;
+        private HashMap<Object, Node> locationForWrite;
+        private HashMap<Object, Node> locationForRead;
+        private Node mergeForWrite;
+        private Node mergeForRead;
+        private int mergeOperationCount;
+        private Node loopCheckPoint;
+        private MemoryMap loopEntryMap;
+
+        public MemoryMap(Block b, MemoryMap memoryMap) {
+            this(b);
+            if (b.firstNode() instanceof LoopBegin) {
+                loopCheckPoint = new WriteMemoryCheckpointNode(b.firstNode().graph());
+                mergeForWrite = loopCheckPoint;
+                mergeForRead = loopCheckPoint;
+                this.loopEntryMap = memoryMap;
+            } else {
+                memoryMap.locationForWrite.putAll(memoryMap.locationForWrite);
+                memoryMap.locationForRead.putAll(memoryMap.locationForRead);
+                mergeForWrite = memoryMap.mergeForWrite;
+                mergeForRead = memoryMap.mergeForRead;
+            }
+        }
+
+        public MemoryMap(Block b) {
+            if (GraalOptions.TraceMemoryMaps) {
+                TTY.println("Creating new memory map for block B" + b.blockID());
+            }
+
+            block = b;
+            locationForWrite = new HashMap<Object, Node>();
+            locationForRead = new HashMap<Object, Node>();
+            StartNode startNode = b.firstNode().graph().start();
+            if (b.firstNode() == startNode) {
+                WriteMemoryCheckpointNode checkpoint = new WriteMemoryCheckpointNode(startNode.graph());
+                checkpoint.setNext((FixedNode) startNode.next());
+                startNode.setNext(checkpoint);
+                mergeForWrite = checkpoint;
+                mergeForRead = checkpoint;
+            }
+        }
+
+        public Node getLoopCheckPoint() {
+            return loopCheckPoint;
+        }
+
+        public MemoryMap getLoopEntryMap() {
+            return loopEntryMap;
+        }
+
+        public void resetMergeOperationCount() {
+            mergeOperationCount = 0;
+        }
+
+        public void mergeWith(MemoryMap memoryMap, Block block) {
+            if (GraalOptions.TraceMemoryMaps) {
+                TTY.println("Merging with memory map of block B" + memoryMap.block.blockID());
+            }
+            mergeForWrite = mergeNodes(mergeForWrite, memoryMap.mergeForWrite, locationForWrite, memoryMap.locationForWrite, block);
+            mergeForRead = mergeNodes(mergeForRead, memoryMap.mergeForRead, locationForRead, memoryMap.locationForRead, block);
+            mergeOperationCount++;
+        }
+
+        private Node mergeNodes(Node mergeLeft, Node mergeRight, HashMap<Object, Node> locationLeft, HashMap<Object, Node> locationRight, Block block) {
+            if (GraalOptions.TraceMemoryMaps) {
+                TTY.println("Merging main merge nodes: " + mergeLeft.id() + " and " + mergeRight.id());
+            }
+
+            for (Entry<Object, Node> e : locationRight.entrySet()) {
+                if (!locationLeft.containsKey(e.getKey())) {
+                    // Only available in right map => create correct node for left map.
+                    if (GraalOptions.TraceMemoryMaps) {
+                        TTY.println("Only right map " + e.getKey());
+                    }
+                    Node leftNode = mergeLeft;
+                    if (leftNode instanceof Phi && ((Phi) leftNode).merge() == block.firstNode()) {
+                        leftNode = leftNode.copyWithEdges();
+                    }
+                    locationLeft.put(e.getKey(), leftNode);
+                }
+            }
+
+            for (Entry<Object, Node> e : locationLeft.entrySet()) {
+                if (locationRight.containsKey(e.getKey())) {
+                    // Available in both maps.
+                    if (GraalOptions.TraceMemoryMaps) {
+                        TTY.println("Merging entries for location " + e.getKey());
+                    }
+                    locationLeft.put(e.getKey(), mergeNodes(e.getValue(), locationRight.get(e.getKey()), block));
+                } else {
+                    // Only available in left map.
+                    if (GraalOptions.TraceMemoryMaps) {
+                        TTY.println("Only available in left map " + e.getKey());
+                    }
+                    locationLeft.put(e.getKey(), mergeNodes(e.getValue(), mergeRight, block));
+                }
+            }
+
+            return mergeNodes(mergeLeft, mergeRight, block);
+        }
+
+        private Node mergeNodes(Node original, Node newValue, Block block) {
+            if (original == newValue) {
+                // Nothing to merge.
+                if (GraalOptions.TraceMemoryMaps) {
+                    TTY.println("Nothing to merge both nodes are " + original.id());
+                }
+                return original;
+            }
+            Merge m = (Merge) block.firstNode();
+            if (original instanceof Phi && ((Phi) original).merge() == m) {
+                Phi phi = (Phi) original;
+                phi.addInput(newValue);
+                if (GraalOptions.TraceMemoryMaps) {
+                    TTY.println("Add new input to phi " + original.id());
+                }
+                assert phi.valueCount() <= phi.merge().endCount();
+                return original;
+            } else {
+                Phi phi = new Phi(CiKind.Illegal, m, PhiType.Memory, m.graph());
+                for (int i = 0; i < mergeOperationCount + 1; ++i) {
+                    phi.addInput(original);
+                }
+                phi.addInput(newValue);
+                if (GraalOptions.TraceMemoryMaps) {
+                    TTY.println("Creating new phi " + phi.id());
+                }
+                assert phi.valueCount() <= phi.merge().endCount() + ((phi.merge() instanceof LoopBegin) ? 1 : 0) : phi.merge() + "/" + phi.valueCount() + "/" + phi.merge().endCount() + "/" + mergeOperationCount;
+                return phi;
+            }
+        }
+
+        public void createWriteMemoryMerge(AbstractMemoryCheckpointNode memMerge) {
+            if (GraalOptions.TraceMemoryMaps) {
+                TTY.println("Creating write memory checkpoint at node " + memMerge.id());
+            }
+
+            // Merge in all writes.
+            for (Entry<Object, Node> writeEntry : locationForWrite.entrySet()) {
+                memMerge.mergedNodes().add(writeEntry.getValue());
+            }
+            locationForWrite.clear();
+            mergeForWrite = memMerge;
+        }
+
+        public void createReadWriteMemoryCheckpoint(AbstractMemoryCheckpointNode memMerge) {
+            if (GraalOptions.TraceMemoryMaps) {
+                TTY.println("Creating readwrite memory checkpoint at node " + memMerge.id());
+            }
+            createWriteMemoryMerge(memMerge);
+            locationForRead.clear();
+            mergeForRead = memMerge;
+        }
+
+        public void registerWrite(WriteNode node) {
+            Object location = node.location().locationIdentity();
+            if (GraalOptions.TraceMemoryMaps) {
+                TTY.println("Register write to " + location + " at node " + node.id());
+            }
+
+            // Create dependency on previous write to same location.
+            node.addDependency(getLocationForWrite(node));
+
+            locationForWrite.put(location, node);
+            locationForRead.put(location, node);
+        }
+
+        public Node getLocationForWrite(WriteNode node) {
+            Object location = node.location().locationIdentity();
+            if (locationForWrite.containsKey(location)) {
+                Node prevWrite = locationForWrite.get(location);
+                return prevWrite;
+            } else {
+                return mergeForWrite;
+            }
+        }
+
+        public void registerRead(ReadNode node) {
+            if (GraalOptions.TraceMemoryMaps) {
+                TTY.println("Register read to node " + node.id());
+            }
+
+            // Create dependency on previous node that creates the memory state for this location.
+            node.addDependency(getLocationForRead(node));
+        }
+
+        public Node getLocationForRead(ReadNode node) {
+            Object location = node.location().locationIdentity();
+            if (locationForRead.containsKey(location)) {
+                return locationForRead.get(location);
+            }
+            return mergeForRead;
+        }
+
+        public void replaceCheckPoint(Node loopCheckPoint) {
+            List<Node> usages = new ArrayList<Node>(loopCheckPoint.usages());
+            for (Node n : usages) {
+                replaceCheckPoint(loopCheckPoint, n);
+            }
+        }
+
+        private void replaceCheckPoint(Node loopCheckPoint, Node n) {
+            if (n instanceof ReadNode) {
+                n.inputs().replace(loopCheckPoint, getLocationForRead((ReadNode) n));
+            } else if (n instanceof WriteNode) {
+                n.inputs().replace(loopCheckPoint, getLocationForWrite((WriteNode) n));
+            } else if (n instanceof WriteMemoryCheckpointNode) {
+                n.inputs().replace(loopCheckPoint, mergeForWrite);
+            } else {
+                n.inputs().replace(loopCheckPoint, mergeForRead);
+            }
+        }
+    }
+
+    @Override
+    protected void run(final Graph graph) {
+        final IdentifyBlocksPhase s = new IdentifyBlocksPhase(false);
+        s.apply(graph);
+
+        List<Block> blocks = s.getBlocks();
+        MemoryMap[] memoryMaps = new MemoryMap[blocks.size()];
+        for (final Block b : blocks) {
+            process(b, memoryMaps, s.getNodeToBlock());
+        }
+    }
+
+    private void process(final Block b, MemoryMap[] memoryMaps, NodeMap<Block> nodeMap) {
+        // Visit every block at most once.
+        if (memoryMaps[b.blockID()] != null) {
+            return;
+        }
+
+        // Process predecessors before this block.
+        for (Block pred : b.getPredecessors()) {
+            process(pred, memoryMaps, nodeMap);
+        }
+
+        // Create initial memory map for the block.
+        MemoryMap map = null;
+        if (b.getPredecessors().size() == 0) {
+            map = new MemoryMap(b);
+        } else {
+            map = new MemoryMap(b, memoryMaps[b.getPredecessors().get(0).blockID()]);
+            for (int i = 1; i < b.getPredecessors().size(); ++i) {
+                assert b.firstNode() instanceof Merge : b.firstNode();
+                Block block = b.getPredecessors().get(i);
+                map.mergeWith(memoryMaps[block.blockID()], b);
+            }
+        }
+
+        // Create the floating memory checkpoint instructions.
+        for (final Node n : b.getInstructions()) {
+            if (n instanceof ReadNode) {
+                ReadNode readNode = (ReadNode) n;
+                readNode.replaceAtPredecessors(readNode.next());
+                readNode.setNext(null);
+                map.registerRead(readNode);
+            } else if (n instanceof WriteNode) {
+                WriteNode writeNode = (WriteNode) n;
+                WriteMemoryCheckpointNode checkpoint = new WriteMemoryCheckpointNode(writeNode.graph());
+                checkpoint.setStateAfter(writeNode.stateAfter());
+                writeNode.setStateAfter(null);
+                checkpoint.setNext(writeNode.next());
+                writeNode.setNext(null);
+                writeNode.replaceAtPredecessors(checkpoint);
+                map.registerWrite(writeNode);
+                map.createWriteMemoryMerge(checkpoint);
+            } else if (n instanceof AbstractMemoryCheckpointNode) {
+                map.createReadWriteMemoryCheckpoint((AbstractMemoryCheckpointNode) n);
+            }
+        }
+
+        memoryMaps[b.blockID()] = map;
+        if (b.lastNode() instanceof LoopEnd) {
+            LoopEnd end = (LoopEnd) b.lastNode();
+            LoopBegin begin = end.loopBegin();
+            Block beginBlock = nodeMap.get(begin);
+            MemoryMap memoryMap = memoryMaps[beginBlock.blockID()];
+            assert memoryMap != null : beginBlock.name();
+            assert memoryMap.getLoopEntryMap() != null;
+            memoryMap.getLoopEntryMap().resetMergeOperationCount();
+            memoryMap.getLoopEntryMap().mergeWith(map, beginBlock);
+            Node loopCheckPoint = memoryMap.getLoopCheckPoint();
+            memoryMap.getLoopEntryMap().replaceCheckPoint(loopCheckPoint);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/Phase.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.phases;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.observer.*;
+import com.oracle.max.graal.compiler.schedule.*;
+import com.oracle.max.graal.graph.Graph;
+
+public abstract class Phase {
+
+    private final String name;
+    private String detailedName;
+    private static final ThreadLocal<Phase> currentPhase = new ThreadLocal<Phase>();
+    private final boolean shouldVerify;
+
+    protected Phase() {
+        this.name = this.getClass().getSimpleName();
+        this.shouldVerify = GraalOptions.Verify;
+        this.detailedName = name;
+    }
+
+    protected Phase(String name) {
+        this(name, true);
+    }
+
+    protected Phase(String name, boolean shouldVerify) {
+        this.name = name;
+        this.shouldVerify = shouldVerify;
+        this.detailedName = name;
+    }
+
+    protected void setDetailedName(String detailedName) {
+        this.detailedName = detailedName;
+    }
+
+    public final void apply(Graph graph) {
+        apply(graph, true, true);
+    }
+
+    public final void apply(Graph graph, boolean plotOnError, boolean plot) {
+        assert graph != null && (!shouldVerify || graph.verify());
+
+        int startDeletedNodeCount = graph.getDeletedNodeCount();
+        int startNodeCount = graph.getNodeCount();
+        Phase oldCurrentPhase = null;
+        if (GraalOptions.Time) {
+            oldCurrentPhase = currentPhase.get();
+            currentPhase.set(this);
+            if (oldCurrentPhase != null) {
+                GraalTimers.get(oldCurrentPhase.getName()).stop();
+            }
+            GraalTimers.get(getName()).start();
+        }
+        //System.out.println("Starting Phase " + getName());
+        try {
+            run(graph);
+        } catch (AssertionError t) {
+            GraalCompilation compilation = GraalCompilation.compilation();
+            if (compilation.compiler.isObserved() && plotOnError) {
+                compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "AssertionError in " + detailedName, graph, true, false, true));
+            }
+            throw t;
+        } catch (RuntimeException t) {
+            GraalCompilation compilation = GraalCompilation.compilation();
+            if (compilation.compiler.isObserved() && plotOnError) {
+                compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "RuntimeException in " + detailedName, graph, true, false, true));
+            }
+            throw t;
+        }
+        //System.out.println("Finished Phase " + getName());
+        if (GraalOptions.Time) {
+            GraalTimers.get(getName()).stop();
+            if (oldCurrentPhase != null) {
+                GraalTimers.get(oldCurrentPhase.getName()).start();
+            }
+            currentPhase.set(oldCurrentPhase);
+        }
+        if (GraalOptions.Meter) {
+            int deletedNodeCount = graph.getDeletedNodeCount() - startDeletedNodeCount;
+            int createdNodeCount = graph.getNodeCount() - startNodeCount + deletedNodeCount;
+            GraalMetrics.get(getName().concat(".executed")).increment();
+            GraalMetrics.get(getName().concat(".deletedNodes")).increment(deletedNodeCount);
+            GraalMetrics.get(getName().concat(".createdNodes")).increment(createdNodeCount);
+        }
+        GraalCompilation compilation = GraalCompilation.compilation();
+        if (compilation.compiler.isObserved() && this.getClass() != IdentifyBlocksPhase.class && (plot || GraalOptions.PlotVerbose)) {
+            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After " + detailedName, graph, true, false));
+        }
+
+        assert !shouldVerify || graph.verify();
+
+        // (Item|Graph|Phase|Value)
+    }
+
+    public final String getName() {
+        return name;
+    }
+
+    protected abstract void run(Graph graph);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/ReadEliminationPhase.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.phases;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.graph.*;
+
+public class ReadEliminationPhase extends Phase {
+
+    @Override
+    protected void run(Graph graph) {
+        for (ReadNode n : graph.getNodes(ReadNode.class)) {
+            if (n.dependencies().size() > 0) {
+                Node memoryInput = n.dependencies().get(0);
+                if (memoryInput instanceof WriteNode) {
+                    WriteNode other = (WriteNode) memoryInput;
+                    if (other.object() == n.object() && other.location() == n.location()) {
+                        if (GraalOptions.TraceReadElimination) {
+                            TTY.println("Eliminated memory read " + n + "and replaced with node " + other.value());
+                        }
+                        n.replaceAndDelete(other.value());
+                    }
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/RematerializationPhase.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,285 @@
+/*
+ * 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.max.graal.compiler.phases;
+
+import java.text.*;
+import java.util.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.schedule.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.graph.*;
+
+
+public class RematerializationPhase extends Phase {
+
+    private NodeMap<Block> nodeToBlock;
+    private HashMap<Node, Block> newNodesToBlock;
+    private List<Block> blocks;
+    private UsageProbability[] probablityCache;
+    private boolean ignoreUsages;
+
+    @Override
+    protected void run(Graph graph) {
+        Iterable<Node> modifiedNodes = graph.getModifiedNodes();
+        graph.stopRecordModifications();
+        NodeWorkList work = graph.createNodeWorkList();
+        for (Node modified : modifiedNodes) {
+            if (modified instanceof FloatingNode) {
+                work.add(modified);
+            }
+        }
+
+        if (work.isEmpty()) {
+            return;
+        }
+
+        final IdentifyBlocksPhase s = new IdentifyBlocksPhase(true);
+        s.apply(graph);
+
+        newNodesToBlock = new HashMap<Node, Block>();
+        nodeToBlock = s.getNodeToBlock();
+        blocks = s.getBlocks();
+        probablityCache = new UsageProbability[blocks.size()];
+
+        for (Node node : work) {
+            if (node instanceof Phi || node instanceof Local || node instanceof Constant || node instanceof LocationNode) {
+                continue;
+            }
+            boolean delay = false;
+            for (Node usage : node.usages()) {
+                if (usage instanceof FloatingNode && !(usage instanceof Phi) && work.isInQueue(usage)) {
+                    delay = true;
+                    break;
+                }
+            }
+            if (delay) {
+                work.addAgain(node);
+                continue;
+            }
+            Arrays.fill(probablityCache, null);
+            ignoreUsages = true;
+            Block block = nodeToBlock.get(node);
+            if (block == null) {
+                continue;
+            }
+            UsageProbability usageProbability = usageProbability(node, block);
+            if (usageProbability.probability < GraalOptions.MinimumUsageProbability) {
+                if (ignoreUsages) {
+                    ignoreUsages = false;
+                    Arrays.fill(probablityCache, null);
+                    usageProbability = usageProbability(node, block); // recompute with usage maps
+                }
+                //TTY.println("going to remarterialize " + node + " at " + block + " : " + toString(usageProbability));
+                boolean first = true;
+                for (Block sux : block.getSuccessors()) {
+                    if (first) {
+                        first = false;
+                        continue;
+                    }
+                    usageProbability = usageProbability(node, sux);
+                    List<Node> usages = new LinkedList<Node>();
+                    for (Node usage : usageProbability.usages) {
+                        usages.add(usage);
+                    }
+                    if (!usages.isEmpty()) {
+                        Node copy = node.copyWithEdges();
+                        newNodesToBlock.put(copy, sux);
+                        GraalMetrics.Rematerializations++;
+                        //TTY.println("> Rematerialized " + node + " : " + toString(usageProbability));
+                        for (Node usage : usages) {
+                            usage.inputs().replace(node, copy);
+                            if (usageProbability.phiUsages != null) {
+                                Set<Phi> phis = usageProbability.phiUsages.get(usage);
+                                if (phis != null) {
+                                    for (Phi phi : phis) {
+                                        int index = phi.merge().phiPredecessorIndex(usage);
+                                        assert phi.valueAt(index) == node;
+                                        phi.setValueAt(index, (Value) copy);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private UsageProbability usageProbability(Node n, Block b) {
+        UsageProbability cached = probablityCache[b.blockID()];
+        if (cached != null) {
+            return cached;
+        }
+        if (ignoreUsages) {
+            GraalMetrics.PartialUsageProbability++;
+        } else {
+            GraalMetrics.FullUsageProbability++;
+        }
+        for (Node usage : n.usages()) {
+            if (usage instanceof Phi) {
+                Phi phi = (Phi) usage;
+                Merge merge = phi.merge();
+                for (int i = 0; i < phi.valueCount(); i++) {
+                    if (phi.valueAt(i) == n) {
+                        insertUsageInCache(merge.phiPredecessorAt(i), phi);
+                    }
+                }
+            } else {
+                insertUsageInCache(usage);
+            }
+        }
+        return usageProbability0(n, b);
+    }
+
+    private void insertUsageInCache(Node usage) {
+        insertUsageInCache(usage, null);
+    }
+
+    private void insertUsageInCache(Node usage, Phi phi) {
+        Block block = block(usage);
+        if (block == null) {
+            return;
+        }
+        int blockID = block.blockID();
+        UsageProbability usageProbability = probablityCache[blockID];
+        if (usageProbability == null) {
+            usageProbability = new UsageProbability(usage);
+            probablityCache[blockID] = usageProbability;
+        } else if (!ignoreUsages) {
+            usageProbability.usages.mark(usage);
+        }
+        if (phi != null) {
+            usageProbability.addPhiUsage(phi, usage);
+        }
+    }
+
+    private Block block(Node node) {
+        Block block;
+        if (!nodeToBlock.isNew(node)) {
+            block = nodeToBlock.get(node);
+        } else {
+            block = newNodesToBlock.get(node);
+            assert block != null;
+        }
+        return block;
+    }
+
+    private UsageProbability usageProbability0(Node n, Block b) {
+        //System.out.println("usageProbability0(" + n.id() + ", " + b + ")");
+        UsageProbability cached = probablityCache[b.blockID()];
+        if (cached != null && (cached.computed || ignoreUsages)) {
+            return cached;
+        }
+        UsageProbability result = cached;
+        if (result == null) {
+            result = new UsageProbability(n.graph());
+        }
+        if (b.getSuccessors().size() > 0) {
+            if (b.isLoopEnd()) {
+                Block loopHeader = b.getSuccessors().get(0);
+                assert loopHeader.isLoopHeader();
+                UsageProbability headerUsages = probablityCache[loopHeader.blockID()];
+                if (headerUsages != null) {
+                    result.merge(headerUsages, 1.0);
+                }
+            } else if (b.getSuccessors().size() == 1) {
+                result.merge(usageProbability0(n, b.getSuccessors().get(0)), 1.0);
+            } else {
+                Node lastNode = b.lastNode();
+                if (lastNode instanceof Invoke) {
+                    result.merge(usageProbability0(n, nodeToBlock.get(((Invoke) lastNode).next())), 1.0);
+                    result.merge(usageProbability0(n, nodeToBlock.get(((Invoke) lastNode).exceptionEdge())), 0.0);
+                } else if (lastNode instanceof ControlSplit) {
+                    ControlSplit split = (ControlSplit) lastNode;
+                    for (int i = 0; i < split.blockSuccessorCount(); i++) {
+                        result.merge(usageProbability0(n, nodeToBlock.get(split.blockSuccessor(i))), split.probability(i));
+                    }
+                } else {
+                    throw Util.shouldNotReachHere();
+                }
+            }
+        }
+        probablityCache[b.blockID()] = result;
+        result.computed = true;
+        return result;
+    }
+
+    private class UsageProbability {
+        double probability;
+        NodeBitMap usages;
+        NodeMap<Set<Phi>> phiUsages;
+        boolean computed;
+
+        public UsageProbability(Node usage) {
+            if (!ignoreUsages) {
+                usages = usage.graph().createNodeBitMap();
+                usages.mark(usage);
+            }
+            probability = 1.0;
+        }
+
+        public UsageProbability(Graph graph) {
+            if (!ignoreUsages) {
+                usages = graph.createNodeBitMap();
+            }
+            probability = 0.0;
+        }
+
+        public void merge(UsageProbability sux, double suxProbability) {
+            if (!ignoreUsages) {
+                usages.setUnion(sux.usages);
+            }
+            probability += suxProbability * sux.probability;
+        }
+
+        public void addPhiUsage(Phi phi, Node usage) {
+            if (phiUsages == null) {
+                phiUsages = phi.graph().createNodeMap();
+            }
+            Set<Phi> phis = phiUsages.get(usage);
+            if (phis == null) {
+                phis = new HashSet<Phi>(2);
+                phiUsages.set(usage, phis);
+            }
+            phis.add(phi);
+        }
+    }
+
+    private String toString(UsageProbability up) {
+        NumberFormat nf = NumberFormat.getPercentInstance();
+        StringBuilder sb = new StringBuilder("p=");
+        sb.append(nf.format(up.probability));
+        if (up.usages != null) {
+            sb.append(" U=[");
+            for (Node n : up.usages) {
+                sb.append(n);
+                sb.append(", ");
+            }
+            sb.append("]");
+        }
+        return sb.toString();
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.schedule;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.graph.*;
+
+
+public class Block {
+
+    private int blockID;
+    private final List<Block> successors = new ArrayList<Block>();
+    private final List<Block> predecessors = new ArrayList<Block>();
+    private List<Node> instructions = new ArrayList<Node>();
+    private Block dominator;
+    private Block javaBlock;
+    private final List<Block> dominators = new ArrayList<Block>();
+    private Anchor anchor;
+    private int loopDepth = 0;
+    private int loopIndex = -1;
+
+    private Node firstNode;
+    private Node lastNode;
+
+    public Node firstNode() {
+        return firstNode;
+    }
+
+    public void setFirstNode(Node node) {
+        this.firstNode = node;
+        this.anchor = null;
+    }
+
+    public Block javaBlock() {
+        return javaBlock;
+    }
+
+    public void setJavaBlock(Block javaBlock) {
+        this.javaBlock = javaBlock;
+    }
+
+    public Node lastNode() {
+        return lastNode;
+    }
+
+    public int loopDepth() {
+        return loopDepth;
+    }
+
+    public void setLoopDepth(int i) {
+        loopDepth = i;
+    }
+
+    public int loopIndex() {
+        return loopIndex;
+    }
+
+    public void setLoopIndex(int i) {
+        loopIndex = i;
+    }
+
+    public Anchor createAnchor() {
+        if (anchor == null) {
+            if (firstNode instanceof Anchor) {
+                this.anchor = (Anchor) firstNode;
+            } else if (firstNode == firstNode.graph().start()) {
+                StartNode start = (StartNode) firstNode;
+                if (start.next() instanceof Anchor) {
+                    this.anchor = (Anchor) start.next();
+                } else {
+                    Anchor a = new Anchor(firstNode.graph());
+                    a.setNext((FixedNode) firstNode.graph().start().next());
+                    firstNode.graph().start().setNext(a);
+                    this.anchor = a;
+                }
+            } else if (firstNode instanceof Merge || firstNode instanceof ExceptionObject) {
+                FixedNodeWithNext fixedNode = (FixedNodeWithNext) firstNode;
+                if (fixedNode.next() instanceof Anchor) {
+                    this.anchor = (Anchor) fixedNode.next();
+                } else {
+                    Anchor a = new Anchor(firstNode.graph());
+                    a.setNext(fixedNode.next());
+                    fixedNode.setNext(a);
+                    this.anchor = a;
+                }
+            } else {
+                assert !(firstNode instanceof Anchor);
+                Anchor a = new Anchor(firstNode.graph());
+                assert firstNode.predecessors().size() == 1 : firstNode;
+                Node pred = firstNode.predecessors().get(0);
+                int predIndex = pred.successors().indexOf(firstNode);
+                pred.successors().set(predIndex, a);
+                a.setNext((FixedNode) firstNode);
+                this.anchor = a;
+            }
+        }
+        return anchor;
+    }
+
+    public void setLastNode(Node node) {
+        this.lastNode = node;
+    }
+
+    public List<Block> getSuccessors() {
+        return Collections.unmodifiableList(successors);
+    }
+
+    public void setDominator(Block dominator) {
+        assert this.dominator == null;
+        assert dominator != null;
+        this.dominator = dominator;
+        dominator.dominators.add(this);
+    }
+
+    public List<Block> getDominators() {
+        return Collections.unmodifiableList(dominators);
+    }
+
+    public List<Node> getInstructions() {
+        return instructions;
+    }
+
+    public List<Block> getPredecessors() {
+        return Collections.unmodifiableList(predecessors);
+    }
+
+    public Block(int blockID) {
+        this.blockID = blockID;
+    }
+
+    public void addSuccessor(Block other) {
+        successors.add(other);
+        other.predecessors.add(this);
+    }
+
+    public int blockID() {
+        return blockID;
+    }
+
+    /**
+     * Iterate over this block, its exception handlers, and its successors, in that order.
+     *
+     * @param closure the closure to apply to each block
+     */
+    public void iteratePreOrder(BlockClosure closure) {
+        // XXX: identity hash map might be too slow, consider a boolean array or a mark field
+        iterate(new IdentityHashMap<Block, Block>(), closure);
+    }
+
+    private void iterate(IdentityHashMap<Block, Block> mark, BlockClosure closure) {
+        if (!mark.containsKey(this)) {
+            mark.put(this, this);
+            closure.apply(this);
+
+            iterateReverse(mark, closure, this.successors);
+        }
+    }
+
+    private void iterateReverse(IdentityHashMap<Block, Block> mark, BlockClosure closure, List<Block> list) {
+        for (int i = list.size() - 1; i >= 0; i--) {
+            list.get(i).iterate(mark, closure);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "B" + blockID;
+    }
+
+    public boolean isLoopHeader() {
+        return firstNode instanceof LoopBegin;
+    }
+
+    public boolean isLoopEnd() {
+        return lastNode instanceof LoopEnd;
+    }
+
+    public Block dominator() {
+        return dominator;
+    }
+
+    public void setInstructions(List<Node> instructions) {
+        this.instructions = instructions;
+    }
+
+    public static void iteratePostOrder(List<Block> blocks, BlockClosure closure) {
+        ArrayList<Block> startBlocks = new ArrayList<Block>();
+        for (Block block : blocks) {
+            if (block.getPredecessors().size() == 0) {
+                startBlocks.add(block);
+            }
+        }
+        iteratePostOrder(blocks, closure, startBlocks.toArray(new Block[startBlocks.size()]));
+    }
+
+    public static void iteratePostOrder(List<Block> blocks, BlockClosure closure, Block... startBlocks) {
+        BitMap visited = new BitMap(blocks.size());
+        LinkedList<Block> workList = new LinkedList<Block>();
+        for (Block block : startBlocks) {
+            workList.add(block);
+            visited.set(block.blockID());
+        }
+
+        while (!workList.isEmpty()) {
+            Block b = workList.remove();
+
+            closure.apply(b);
+
+            for (Block succ : b.getSuccessors()) {
+                if (!visited.get(succ.blockID())) {
+                    boolean delay = false;
+                    for (Block pred : succ.getPredecessors()) {
+                        if (!visited.get(pred.blockID()) && !(pred.lastNode instanceof LoopEnd)) {
+                            delay = true;
+                            break;
+                        }
+                    }
+
+                    if (!delay) {
+                        visited.set(succ.blockID());
+                        workList.add(succ);
+                    }
+                }
+            }
+        }
+    }
+
+    public String name() {
+        return "B" + blockID;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,591 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.schedule;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.phases.*;
+import com.oracle.max.graal.compiler.value.*;
+import com.oracle.max.graal.graph.*;
+
+
+public class IdentifyBlocksPhase extends Phase {
+    private final List<Block> blocks = new ArrayList<Block>();
+    private NodeMap<Block> nodeToBlock;
+    private Graph graph;
+    private boolean scheduleAllNodes;
+    private int loopCount;
+
+    public IdentifyBlocksPhase(boolean scheduleAllNodes) {
+        super(scheduleAllNodes ? "FullSchedule" : "PartSchedule", false);
+        this.scheduleAllNodes = scheduleAllNodes;
+    }
+
+
+    @Override
+    protected void run(Graph graph) {
+        this.graph = graph;
+        nodeToBlock = graph.createNodeMap();
+        identifyBlocks();
+    }
+
+    public List<Block> getBlocks() {
+        return Collections.unmodifiableList(blocks);
+    }
+
+    public NodeMap<Block> getNodeToBlock() {
+        return nodeToBlock;
+    }
+
+    private Block createBlock() {
+        Block b = new Block(blocks.size());
+        blocks.add(b);
+        return b;
+    }
+
+    public int loopCount() {
+        return loopCount;
+    }
+
+    private Block assignBlockNew(Node n, Block b) {
+        if (b == null) {
+            b = createBlock();
+        }
+
+        assert nodeToBlock.get(n) == null;
+        nodeToBlock.set(n, b);
+
+        if (n instanceof Merge) {
+            for (Node usage : n.usages()) {
+
+                if (usage instanceof Phi) {
+                    nodeToBlock.set(usage, b);
+                }
+
+                if (usage instanceof LoopCounter) {
+                    nodeToBlock.set(usage, b);
+                }
+
+            }
+        }
+        if (b.lastNode() == null) {
+            b.setFirstNode(n);
+            b.setLastNode(n);
+            b.getInstructions().add(n);
+        } else {
+            b.getInstructions().add(0, n);
+            b.setFirstNode(n);
+        }
+
+        return b;
+    }
+
+    public static boolean isFixed(Node n) {
+        return n != null && ((n instanceof FixedNode) || n == n.graph().start());
+    }
+
+    public static boolean isBlockEnd(Node n) {
+        return trueSuccessorCount(n) > 1 || n instanceof Return || n instanceof Unwind || n instanceof Deoptimize;
+    }
+
+    private void print() {
+        Block dominatorRoot = nodeToBlock.get(graph.start());
+        System.out.println("Root = " + dominatorRoot);
+        System.out.println("nodeToBlock :");
+        System.out.println(nodeToBlock);
+        System.out.println("Blocks :");
+        for (Block b : blocks) {
+            System.out.println(b + " [S:" + b.getSuccessors() + ", P:" + b.getPredecessors() + ", D:" + b.getDominators());
+            System.out.println("  f " + b.firstNode());
+            for (Node n : b.getInstructions()) {
+                System.out.println("  - " + n);
+            }
+            System.out.println("  l " + b.lastNode());
+        }
+    }
+
+    private void identifyBlocks() {
+
+        // Identify blocks.
+        for (Node n : graph.getNodes()) {
+            if (n instanceof EndNode || n instanceof Return || n instanceof Unwind || n instanceof LoopEnd || n instanceof Deoptimize) {
+                Block block = null;
+                Node currentNode = n;
+                while (nodeToBlock.get(currentNode) == null) {
+                    if (block != null && (currentNode instanceof ControlSplit || trueSuccessorCount(currentNode) > 1)) {
+                        // We are at a split node => start a new block.
+                        block = null;
+                    }
+                    block = assignBlockNew(currentNode, block);
+                    if (currentNode.predecessors().size() == 0) {
+                        // Either dead code or at a merge node => stop iteration.
+                        break;
+                    }
+                    Node prev = currentNode;
+                    currentNode = currentNode.singlePredecessor();
+                    assert !currentNode.isDeleted() : prev + " " + currentNode;
+                }
+            }
+        }
+
+        // Connect blocks.
+        for (Block block : blocks) {
+            Node n = block.firstNode();
+            if (n instanceof Merge) {
+                Merge m = (Merge) n;
+                for (Node pred : m.cfgPredecessors()) {
+                    Block predBlock = nodeToBlock.get(pred);
+                    predBlock.addSuccessor(block);
+                }
+            } else {
+                for (Node pred : n.predecessors()) {
+                    if (isFixed(pred)) {
+                        Block predBlock = nodeToBlock.get(pred);
+                        predBlock.addSuccessor(block);
+                    }
+                }
+            }
+        }
+
+        computeDominators();
+
+
+        if (scheduleAllNodes) {
+            computeLoopInformation(); // Will make the graph cyclic.
+            assignLatestPossibleBlockToNodes();
+            sortNodesWithinBlocks();
+        } else {
+            computeJavaBlocks();
+        }
+    }
+
+    private void computeLoopInformation() {
+
+        // Add successors of loop end nodes. Makes the graph cyclic.
+        for (Block block : blocks) {
+            Node n = block.lastNode();
+            if (n instanceof LoopEnd) {
+                LoopEnd loopEnd = (LoopEnd) n;
+                assert loopEnd.loopBegin() != null;
+                Block loopBeginBlock = nodeToBlock.get(loopEnd.loopBegin());
+                block.addSuccessor(loopBeginBlock);
+                BitMap map = new BitMap(blocks.size());
+                markBlocks(block, loopBeginBlock, map, loopCount++, block.loopDepth());
+                assert loopBeginBlock.loopDepth() == block.loopDepth() && loopBeginBlock.loopIndex() == block.loopIndex();
+            }
+        }
+
+//        for (Block block : blocks) {
+//            TTY.println("Block B" + block.blockID() + " loopIndex=" + block.loopIndex() + ", loopDepth=" + block.loopDepth());
+//        }
+    }
+
+    private void markBlocks(Block block, Block endBlock, BitMap map, int loopIndex, int initialDepth) {
+        if (map.get(block.blockID())) {
+            return;
+        }
+
+        map.set(block.blockID());
+        if (block.loopDepth() <= initialDepth) {
+            assert block.loopDepth() == initialDepth;
+            block.setLoopIndex(loopIndex);
+        }
+        block.setLoopDepth(block.loopDepth() + 1);
+
+        if (block == endBlock) {
+            return;
+        }
+
+        for (Block pred : block.getPredecessors()) {
+            markBlocks(pred, endBlock, map, loopIndex, initialDepth);
+        }
+
+        if (block.isLoopHeader()) {
+            markBlocks(nodeToBlock.get(((LoopBegin) block.firstNode()).loopEnd()), endBlock, map, loopIndex, initialDepth);
+        }
+    }
+
+    private void computeJavaBlocks() {
+
+        for (Block b : blocks) {
+            computeJavaBlock(b);
+        }
+    }
+
+    private Block computeJavaBlock(Block b) {
+        if (b.javaBlock() == null) {
+            if (b.getPredecessors().size() == 0) {
+                b.setJavaBlock(b);
+            } else if (b.getPredecessors().size() == 1) {
+                Block pred = b.getPredecessors().get(0);
+                if (pred.getSuccessors().size() > 1) {
+                    b.setJavaBlock(b);
+                } else {
+                    b.setJavaBlock(computeJavaBlock(pred));
+                }
+            } else {
+                Block dominatorBlock = b.getPredecessors().get(0);
+                for (int i = 1; i < b.getPredecessors().size(); ++i) {
+                    dominatorBlock = getCommonDominator(dominatorBlock, b.getPredecessors().get(i));
+                }
+                BitMap blockMap = new BitMap(blocks.size());
+                markPredecessors(b, dominatorBlock, blockMap);
+
+                Block result = dominatorBlock;
+                L1: for (Block curBlock : blocks) {
+                    if (curBlock != b && blockMap.get(curBlock.blockID())) {
+                        for (Block succ : curBlock.getSuccessors()) {
+                            if (!blockMap.get(succ.blockID())) {
+                                result = b;
+                                break L1;
+                            }
+                        }
+                    }
+                }
+                b.setJavaBlock(result);
+            }
+        }
+        return b.javaBlock();
+    }
+
+    private void markPredecessors(Block b, Block stopBlock, BitMap blockMap) {
+        if (blockMap.get(b.blockID())) {
+            return;
+        }
+        blockMap.set(b.blockID());
+        if (b != stopBlock) {
+            for (Block pred : b.getPredecessors()) {
+                markPredecessors(pred, stopBlock, blockMap);
+            }
+        }
+    }
+
+    private void assignLatestPossibleBlockToNodes() {
+        for (Node n : graph.getNodes()) {
+            assignLatestPossibleBlockToNode(n);
+        }
+    }
+
+    private Block assignLatestPossibleBlockToNode(Node n) {
+        if (n == null) {
+            return null;
+        }
+
+        assert !n.isDeleted();
+
+        Block prevBlock = nodeToBlock.get(n);
+        if (prevBlock != null) {
+            return prevBlock;
+        }
+
+        Block block = null;
+        for (Node succ : n.successors()) {
+            block = getCommonDominator(block, assignLatestPossibleBlockToNode(succ));
+        }
+        for (Node usage : n.usages()) {
+            if (usage instanceof Phi) {
+                Phi phi = (Phi) usage;
+                Merge merge = phi.merge();
+                Block mergeBlock = nodeToBlock.get(merge);
+                assert mergeBlock != null : "no block for merge " + merge.id();
+                for (int i = 0; i < phi.valueCount(); ++i) {
+                    if (phi.valueAt(i) == n) {
+                        if (mergeBlock.getPredecessors().size() <= i) {
+                            TTY.println(merge.toString());
+                            TTY.println(phi.toString());
+                            TTY.println(merge.phiPredecessors().toString());
+                            TTY.println(phi.inputs().toString());
+                            TTY.println("value count: " + phi.valueCount());
+                        }
+                        block = getCommonDominator(block, mergeBlock.getPredecessors().get(i));
+                    }
+                }
+            } else if (usage instanceof FrameState && ((FrameState) usage).block() != null) {
+                Merge merge = ((FrameState) usage).block();
+                for (Node pred : merge.cfgPredecessors()) {
+                    block = getCommonDominator(block, nodeToBlock.get(pred));
+                }
+            } else if (usage instanceof LoopCounter) {
+                LoopCounter counter = (LoopCounter) usage;
+                if (n == counter.init() || n == counter.stride()) {
+                    LoopBegin loopBegin = counter.loopBegin();
+                    Block mergeBlock = nodeToBlock.get(loopBegin);
+                    block = getCommonDominator(block, mergeBlock.dominator());
+                }
+            } else {
+                block = getCommonDominator(block, assignLatestPossibleBlockToNode(usage));
+            }
+        }
+
+
+        if (block != null) {
+            if (GraalOptions.OptOptimisticSchedule) {
+                block = scheduleOutOfLoops(n, block);
+            }
+            nodeToBlock.set(n, block);
+            block.getInstructions().add(n);
+        }
+        return block;
+    }
+
+    private Block scheduleOutOfLoops(Node n, Block latestBlock) {
+        Block cur = latestBlock;
+        while (cur.loopDepth() != 0) {
+            if (cur.isLoopHeader()) {
+                assert cur.getPredecessors().size() == 2 : cur.getPredecessors().size();
+                if (canSchedule(n, cur.getPredecessors().get(0))) {
+                   // TTY.println("can schedule out of loop!" + n);
+                    return scheduleOutOfLoops(n, cur.getPredecessors().get(0));
+                } else {
+                    break;
+                }
+            }
+            Block prev = cur;
+            cur = cur.dominator();
+
+            // This must be a loop exit.
+            if (cur.loopDepth() > prev.loopDepth()) {
+//                TTY.println("break out because of different loop depth");
+                break;
+            }
+        }
+        return latestBlock;
+    }
+
+    private boolean canSchedule(Node n, Block block) {
+        Set<Block> allowedBlocks = new HashSet<Block>();
+        Block cur = block;
+        while (cur != null) {
+            allowedBlocks.add(cur);
+            cur = cur.dominator();
+        }
+        // Now we know the allowed blocks for inputs and predecessors.
+        return checkNodesAbove(allowedBlocks, n);
+    }
+
+    private boolean checkNodesAbove(Set<Block> allowedBlocks, Node n) {
+        if (n == null) {
+            return true;
+        }
+
+        if (nodeToBlock.get(n) != null) {
+            return allowedBlocks.contains(nodeToBlock.get(n));
+        } else {
+            assert !(n instanceof Phi) : ((Phi) n).merge();
+            for (Node input : n.inputs()) {
+                if (!checkNodesAbove(allowedBlocks, input)) {
+                    return false;
+                }
+            }
+            for (Node pred : n.predecessors()) {
+                if (!checkNodesAbove(allowedBlocks, pred)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+
+
+    private Block getCommonDominator(Block a, Block b) {
+        if (a == null) {
+            return b;
+        }
+        if (b == null) {
+            return a;
+        }
+        return commonDominator(a, b);
+    }
+
+    private void sortNodesWithinBlocks() {
+        NodeBitMap map = graph.createNodeBitMap();
+        for (Block b : blocks) {
+            sortNodesWithinBlocks(b, map);
+        }
+    }
+
+    private void sortNodesWithinBlocks(Block b, NodeBitMap map) {
+        List<Node> instructions = b.getInstructions();
+        List<Node> sortedInstructions = new ArrayList<Node>(instructions.size() + 2);
+
+        assert !map.isMarked(b.firstNode()) && nodeToBlock.get(b.firstNode()) == b;
+        assert !map.isMarked(b.lastNode()) && nodeToBlock.get(b.lastNode()) == b;
+
+        for (Node i : instructions) {
+            addToSorting(b, i, sortedInstructions, map);
+        }
+
+        // Make sure that last node gets really last (i.e. when a frame state successor hangs off it).
+        Node lastSorted = sortedInstructions.get(sortedInstructions.size() - 1);
+        if (lastSorted != b.lastNode()) {
+            int idx = sortedInstructions.indexOf(b.lastNode());
+            boolean canNotMove = false;
+            for (int i = idx + 1; i < sortedInstructions.size(); i++) {
+                if (sortedInstructions.get(i).inputs().contains(b.lastNode())) {
+                    canNotMove = true;
+                    break;
+                }
+            }
+            if (canNotMove) {
+                assert !(b.lastNode() instanceof ControlSplit);
+                //b.setLastNode(lastSorted);
+            } else {
+                sortedInstructions.remove(b.lastNode());
+                sortedInstructions.add(b.lastNode());
+            }
+        }
+        b.setInstructions(sortedInstructions);
+//        TTY.println();
+//        TTY.println("B" + b.blockID());
+//        for (Node n : sortedInstructions) {
+//            TTY.println("n=" + n);
+//        }
+    }
+
+    private void addToSorting(Block b, Node i, List<Node> sortedInstructions, NodeBitMap map) {
+        if (i == null || map.isMarked(i) || nodeToBlock.get(i) != b || i instanceof Phi || i instanceof Local || i instanceof LoopCounter) {
+            return;
+        }
+
+        if (i instanceof WriteNode) {
+            // TODO(tw): Make sure every ReadNode that is connected to the same memory state is executed before every write node.
+            // WriteNode wn = (WriteNode) i;
+        }
+
+        FrameState state = null;
+        WriteNode writeNode = null;
+        for (Node input : i.inputs()) {
+            if (input instanceof WriteNode && !map.isMarked(input) && nodeToBlock.get(input) == b) {
+                writeNode = (WriteNode) input;
+            } else if (input instanceof FrameState) {
+                state = (FrameState) input;
+            } else {
+                addToSorting(b, input, sortedInstructions, map);
+            }
+        }
+
+        for (Node pred : i.predecessors()) {
+            addToSorting(b, pred, sortedInstructions, map);
+        }
+
+        map.mark(i);
+
+        addToSorting(b, state, sortedInstructions, map);
+        assert writeNode == null || !map.isMarked(writeNode);
+        addToSorting(b, writeNode, sortedInstructions, map);
+
+        // Now predecessors and inputs are scheduled => we can add this node.
+        sortedInstructions.add(i);
+    }
+
+    private void computeDominators() {
+        Block dominatorRoot = nodeToBlock.get(graph.start());
+        assert dominatorRoot.getPredecessors().size() == 0;
+        BitMap visited = new BitMap(blocks.size());
+        visited.set(dominatorRoot.blockID());
+        LinkedList<Block> workList = new LinkedList<Block>();
+        for (Block block : blocks) {
+            if (block.getPredecessors().size() == 0) {
+                workList.add(block);
+            }
+        }
+
+        int cnt = 0;
+        while (!workList.isEmpty()) {
+            if (cnt++ > blocks.size() * 20) {
+                throw new RuntimeException("(ls) endless loop in computeDominators?");
+            }
+            Block b = workList.remove();
+
+            List<Block> predecessors = b.getPredecessors();
+            if (predecessors.size() == 1) {
+                b.setDominator(predecessors.get(0));
+            } else if (predecessors.size() > 0) {
+                boolean delay = false;
+                for (Block pred : predecessors) {
+                    if (pred != dominatorRoot && pred.dominator() == null) {
+                        delay = true;
+                        break;
+                    }
+                }
+
+                if (delay) {
+                    workList.add(b);
+                    continue;
+                }
+
+                Block dominator = null;
+                for (Block pred : predecessors) {
+                    if (dominator == null) {
+                        dominator = pred;
+                    } else {
+                        dominator = commonDominator(dominator, pred);
+                    }
+                }
+                b.setDominator(dominator);
+            }
+
+            for (Block succ : b.getSuccessors()) {
+                if (!visited.get(succ.blockID())) {
+                    visited.set(succ.blockID());
+                    workList.add(succ);
+                }
+            }
+        }
+    }
+
+    public Block commonDominator(Block a, Block b) {
+        BitMap bitMap = new BitMap(blocks.size());
+        Block cur = a;
+        while (cur != null) {
+            bitMap.set(cur.blockID());
+            cur = cur.dominator();
+        }
+
+        cur = b;
+        while (cur != null) {
+            if (bitMap.get(cur.blockID())) {
+                return cur;
+            }
+            cur = cur.dominator();
+        }
+
+        throw new IllegalStateException("no common dominator between " + a + " and " + b);
+    }
+
+    public static int trueSuccessorCount(Node n) {
+        if (n == null) {
+            return 0;
+        }
+        int i = 0;
+        for (Node s : n.successors()) {
+            if (isFixed(s)) {
+                i++;
+            }
+        }
+        return i;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/Backend.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.target;
+
+import java.lang.reflect.*;
+
+import com.oracle.max.asm.*;
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.compiler.globalstub.*;
+import com.oracle.max.graal.compiler.lir.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+import com.sun.cri.xir.*;
+
+/**
+ * The {@code Backend} class represents a compiler backend for Graal.
+ *
+ * @author Ben L. Titzer
+ */
+public abstract class Backend {
+    public final GraalCompiler compiler;
+
+    protected Backend(GraalCompiler compiler) {
+        this.compiler = compiler;
+    }
+
+    public static Backend create(CiArchitecture arch, GraalCompiler compiler) {
+        String className = arch.getClass().getName().replace("com.oracle.max.asm", "com.oracle.max.graal.compiler") + "Backend";
+        try {
+            Class<?> c = Class.forName(className);
+            Constructor<?> cons = c.getDeclaredConstructor(GraalCompiler.class);
+            return (Backend) cons.newInstance(compiler);
+        } catch (Exception e) {
+            throw new Error("Could not instantiate " + className, e);
+        }
+    }
+
+    public abstract FrameMap newFrameMap(RiMethod method, int numberOfLocks);
+    public abstract LIRGenerator newLIRGenerator(GraalCompilation compilation);
+    public abstract LIRAssembler newLIRAssembler(GraalCompilation compilation);
+    public abstract AbstractAssembler newAssembler(RiRegisterConfig registerConfig);
+    public abstract GlobalStubEmitter newGlobalStubEmitter();
+    public abstract CiXirAssembler newXirAssembler();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64Backend.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.target.amd64;
+
+import static com.oracle.max.graal.compiler.GraalCompilation.*;
+
+import com.oracle.max.asm.*;
+import com.oracle.max.asm.target.amd64.*;
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.compiler.globalstub.*;
+import com.oracle.max.graal.compiler.lir.*;
+import com.oracle.max.graal.compiler.target.*;
+import com.sun.cri.ri.*;
+import com.sun.cri.xir.*;
+
+/**
+ * The {@code X86Backend} class represents the backend for the AMD64 architecture.
+ *
+ * @author Ben L. Titzer
+ */
+public class AMD64Backend extends Backend {
+
+    public AMD64Backend(GraalCompiler compiler) {
+        super(compiler);
+    }
+    /**
+     * Creates a new LIRGenerator for x86.
+     * @param compilation the compilation for which to create the LIR generator
+     * @return an appropriate LIR generator instance
+     */
+    @Override
+    public LIRGenerator newLIRGenerator(GraalCompilation compilation) {
+        return new AMD64LIRGenerator(compilation);
+    }
+
+    /**
+     * Creates a new LIRAssembler for x86.
+     * @param compilation the compilation for which to create the LIR assembler
+     * @return an appropriate LIR assembler instance
+     */
+    @Override
+    public LIRAssembler newLIRAssembler(GraalCompilation compilation) {
+        return new AMD64LIRAssembler(compilation);
+    }
+
+    @Override
+    public FrameMap newFrameMap(RiMethod method, int numberOfLocks) {
+        return new FrameMap(compilation(), method, numberOfLocks);
+    }
+    @Override
+    public AbstractAssembler newAssembler(RiRegisterConfig registerConfig) {
+        return new AMD64MacroAssembler(compiler.target, registerConfig);
+    }
+
+    @Override
+    public CiXirAssembler newXirAssembler() {
+        return new AMD64XirAssembler();
+    }
+
+    @Override
+    public GlobalStubEmitter newGlobalStubEmitter() {
+        return new AMD64GlobalStubEmitter(compiler);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64GlobalStubEmitter.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,439 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.target.amd64;
+
+import static com.sun.cri.ci.CiCallingConvention.Type.*;
+
+import java.util.*;
+
+import com.oracle.max.asm.*;
+import com.oracle.max.asm.target.amd64.*;
+import com.oracle.max.asm.target.amd64.AMD64Assembler.*;
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.asm.*;
+import com.oracle.max.graal.compiler.globalstub.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ci.CiRegister.*;
+import com.sun.cri.ri.*;
+import com.sun.cri.xir.*;
+import com.sun.cri.xir.CiXirAssembler.*;
+
+public class AMD64GlobalStubEmitter implements GlobalStubEmitter {
+
+    public static final int ARGUMENT_SIZE = 8;
+
+    private static final long FloatSignFlip = 0x8000000080000000L;
+    private static final long DoubleSignFlip = 0x8000000000000000L;
+    private static final CiRegister convertArgument = AMD64.xmm0;
+    private static final CiRegister convertResult = AMD64.rax;
+    private static final CiRegister negateArgument = AMD64.xmm0;
+    private static final CiRegister negateTemp = AMD64.xmm1;
+
+    private TargetMethodAssembler tasm;
+    private AMD64MacroAssembler asm;
+    private final CiTarget target;
+    private int argsSize;
+    private int[] argOffsets;
+    private int resultOffset;
+    private int saveSize;
+    private int registerRestoreEpilogueOffset;
+
+    private RiRuntime runtime;
+    private GraalCompiler compiler;
+    private CiRegister[] registersSaved;
+
+    private boolean savedAllRegisters;
+
+    public AMD64GlobalStubEmitter(GraalCompiler compiler) {
+        this.compiler = compiler;
+        this.target = compiler.target;
+        this.runtime = compiler.runtime;
+    }
+
+    private void reset(CiKind resultKind, CiKind[] argTypes) {
+        asm = new AMD64MacroAssembler(compiler.target, compiler.globalStubRegisterConfig);
+        tasm = new TargetMethodAssembler(asm);
+        saveSize = 0;
+        argsSize = 0;
+        argOffsets = new int[argTypes.length];
+        resultOffset = 0;
+        registerRestoreEpilogueOffset = -1;
+        registersSaved = null;
+
+        for (int i = 0; i < argTypes.length; i++) {
+            argOffsets[i] = argsSize;
+            argsSize += ARGUMENT_SIZE;
+        }
+
+        if (resultKind != CiKind.Void) {
+            if (argsSize == 0) {
+                argsSize = ARGUMENT_SIZE;
+            }
+            resultOffset = 0;
+        }
+    }
+
+    public GlobalStub emit(CiRuntimeCall runtimeCall, RiRuntime runtime) {
+        reset(runtimeCall.resultKind, runtimeCall.arguments);
+        emitStandardForward(null, runtimeCall);
+        String name = "stub-" + runtimeCall;
+        CiTargetMethod targetMethod = tasm.finishTargetMethod(name, runtime, registerRestoreEpilogueOffset, true);
+        Object stubObject = runtime.registerCompilerStub(targetMethod, name);
+        return new GlobalStub(null, runtimeCall.resultKind, stubObject, argsSize, argOffsets, resultOffset);
+    }
+
+    public GlobalStub emit(GlobalStub.Id stub, RiRuntime runtime) {
+        reset(stub.resultKind, stub.arguments);
+
+        switch (stub) {
+            case f2i:
+                emitF2I();
+                break;
+            case f2l:
+                emitF2L();
+                break;
+            case d2i:
+                emitD2I();
+                break;
+            case d2l:
+                emitD2L();
+                break;
+            case fneg:
+                emitFNEG();
+                break;
+            case dneg:
+                emitDNEG();
+                break;
+        }
+
+        String name = "stub-" + stub;
+        CiTargetMethod targetMethod = tasm.finishTargetMethod(name, runtime, registerRestoreEpilogueOffset, true);
+        Object stubObject = runtime.registerCompilerStub(targetMethod, name);
+        return new GlobalStub(stub, stub.resultKind, stubObject, argsSize, argOffsets, resultOffset);
+    }
+
+    private CiValue allocateParameterOperand(XirParameter param, int parameterIndex) {
+        return new CiAddress(param.kind, AMD64.RSP, argumentIndexToStackOffset(parameterIndex));
+    }
+
+    private CiValue allocateResultOperand(XirOperand result) {
+        return new CiAddress(result.kind, AMD64.RSP, argumentIndexToStackOffset(0));
+    }
+
+    private CiValue allocateOperand(XirTemp temp, ArrayList<CiRegister> allocatableRegisters) {
+        if (temp instanceof XirRegister) {
+            XirRegister fixed = (XirRegister) temp;
+            return fixed.register;
+        }
+
+        return newRegister(temp.kind, allocatableRegisters);
+    }
+
+    private CiValue newRegister(CiKind kind, ArrayList<CiRegister> allocatableRegisters) {
+        assert kind != CiKind.Float && kind != CiKind.Double;
+        assert allocatableRegisters.size() > 0;
+        return allocatableRegisters.remove(allocatableRegisters.size() - 1).asValue(kind);
+    }
+
+    public GlobalStub emit(XirTemplate template, RiRuntime runtime) {
+        GraalCompilation compilation = new GraalCompilation(compiler, null, -1, null);
+        try {
+            return emit(template, compilation);
+        } finally {
+            compilation.close();
+        }
+    }
+
+    public GlobalStub emit(XirTemplate template, GraalCompilation compilation) {
+        reset(template.resultOperand.kind, getArgumentKinds(template));
+        compilation.initFrameMap(0);
+        compilation.frameMap().setFrameSize(frameSize());
+        AMD64LIRAssembler assembler = new AMD64LIRAssembler(compilation);
+        asm = assembler.masm;
+        tasm = assembler.tasm;
+
+        ArrayList<CiRegister> allocatableRegisters = new ArrayList<CiRegister>(Arrays.asList(compiler.globalStubRegisterConfig.getCategorizedAllocatableRegisters().get(RegisterFlag.CPU)));
+        for (XirTemp t : template.temps) {
+            if (t instanceof XirRegister) {
+                final XirRegister fixed = (XirRegister) t;
+                if (fixed.register.isRegister()) {
+                    allocatableRegisters.remove(fixed.register.asRegister());
+                }
+            }
+        }
+
+        completeSavePrologue();
+
+        CiValue[] operands = new CiValue[template.variableCount];
+
+        XirOperand resultOperand = template.resultOperand;
+
+        if (template.allocateResultOperand) {
+            CiValue outputOperand = CiValue.IllegalValue;
+            // This snippet has a result that must be separately allocated
+            // Otherwise it is assumed that the result is part of the inputs
+            if (resultOperand.kind != CiKind.Void && resultOperand.kind != CiKind.Illegal) {
+                outputOperand = allocateResultOperand(resultOperand);
+                assert operands[resultOperand.index] == null;
+            }
+            operands[resultOperand.index] = outputOperand;
+        }
+
+        for (XirParameter param : template.parameters) {
+            assert !(param instanceof XirConstantOperand) : "constant parameters not supported for stubs";
+            CiValue op = allocateParameterOperand(param, param.parameterIndex);
+            assert operands[param.index] == null;
+
+            // Is the value destroyed?
+            if (template.isParameterDestroyed(param.parameterIndex)) {
+                CiValue newOp = newRegister(op.kind, allocatableRegisters);
+                assembler.moveOp(op, newOp, op.kind, null, false);
+                operands[param.index] = newOp;
+            } else {
+                operands[param.index] = op;
+            }
+        }
+
+        for (XirConstant c : template.constants) {
+            assert operands[c.index] == null;
+            operands[c.index] = c.value;
+        }
+
+        for (XirTemp t : template.temps) {
+            CiValue op = allocateOperand(t, allocatableRegisters);
+            assert operands[t.index] == null;
+            operands[t.index] = op;
+        }
+
+        for (CiValue operand : operands) {
+            assert operand != null;
+        }
+
+        Label[] labels = new Label[template.labels.length];
+        for (int i = 0; i < labels.length; i++) {
+            labels[i] = new Label();
+        }
+
+        assert template.marks.length == 0 : "marks not supported in global stubs";
+        assembler.emitXirInstructions(null, template.fastPath, labels, operands, null);
+        epilogue();
+        CiTargetMethod targetMethod = tasm.finishTargetMethod(template.name, runtime, registerRestoreEpilogueOffset, true);
+        Object stubObject = runtime.registerCompilerStub(targetMethod, template.name);
+        return new GlobalStub(null, template.resultOperand.kind, stubObject, argsSize, argOffsets, resultOffset);
+    }
+
+    private CiKind[] getArgumentKinds(XirTemplate template) {
+        CiXirAssembler.XirParameter[] params = template.parameters;
+        CiKind[] result = new CiKind[params.length];
+        for (int i = 0; i < params.length; i++) {
+            result[i] = params[i].kind;
+        }
+        return result;
+    }
+
+    private void negatePrologue() {
+        partialSavePrologue(negateArgument, negateTemp);
+        loadArgument(0, negateArgument);
+    }
+
+    private void negateEpilogue() {
+        storeArgument(0, negateArgument);
+        epilogue();
+    }
+
+    private void emitDNEG() {
+        negatePrologue();
+        asm.movsd(negateTemp, tasm.recordDataReferenceInCode(CiConstant.forLong(DoubleSignFlip)));
+        asm.xorpd(negateArgument, negateTemp);
+        negateEpilogue();
+    }
+
+    private void emitFNEG() {
+        negatePrologue();
+        asm.movsd(negateTemp, tasm.recordDataReferenceInCode(CiConstant.forLong(FloatSignFlip)));
+        asm.xorps(negateArgument, negateTemp);
+        negateEpilogue();
+    }
+
+    private void convertPrologue() {
+        partialSavePrologue(convertArgument, convertResult);
+        loadArgument(0, convertArgument);
+    }
+
+    private void convertEpilogue() {
+        storeArgument(0, convertResult);
+        epilogue();
+    }
+
+    private void emitD2L() {
+        emitCOMISSD(true, false);
+    }
+
+    private void emitD2I() {
+        emitCOMISSD(true, true);
+    }
+
+    private void emitF2L() {
+        emitCOMISSD(false, false);
+    }
+
+    private void emitF2I() {
+        emitCOMISSD(false, true);
+    }
+
+    private void emitCOMISSD(boolean isDouble, boolean isInt) {
+        convertPrologue();
+        if (isDouble) {
+            asm.ucomisd(convertArgument, tasm.recordDataReferenceInCode(CiConstant.DOUBLE_0));
+        } else {
+            asm.ucomiss(convertArgument, tasm.recordDataReferenceInCode(CiConstant.FLOAT_0));
+        }
+        Label nan = new Label();
+        Label ret = new Label();
+        asm.jccb(ConditionFlag.parity, nan);
+        asm.jccb(ConditionFlag.below, ret);
+
+        // input is > 0 -> return maxInt
+        // result register already contains 0x80000000, so subtracting 1 gives 0x7fffffff
+        asm.decrementl(convertResult, 1);
+        asm.jmpb(ret);
+
+        // input is NaN -> return 0
+        asm.bind(nan);
+        asm.xorptr(convertResult, convertResult);
+
+        asm.bind(ret);
+        convertEpilogue();
+    }
+
+    private void emitStandardForward(GlobalStub.Id stub, CiRuntimeCall call) {
+        if (stub != null) {
+            assert stub.resultKind == call.resultKind;
+            assert stub.arguments.length == call.arguments.length;
+            for (int i = 0; i < stub.arguments.length; i++) {
+                assert stub.arguments[i] == call.arguments[i];
+            }
+        }
+
+        completeSavePrologue();
+        forwardRuntimeCall(call);
+        epilogue();
+    }
+
+    private int argumentIndexToStackOffset(int index) {
+        // <-- lower addresses
+        // | stub frame              | caller frame   |
+        // | locals,savearea,retaddr | args .....     |
+        return frameSize() + (index + 1) * ARGUMENT_SIZE;
+    }
+
+    private void loadArgument(int index, CiRegister register) {
+        asm.movq(register, new CiAddress(CiKind.Word, AMD64.RSP, argumentIndexToStackOffset(index)));
+    }
+
+    private void storeArgument(int index, CiRegister register) {
+        asm.movq(new CiAddress(CiKind.Word, AMD64.RSP, argumentIndexToStackOffset(index)), register);
+    }
+
+    private void partialSavePrologue(CiRegister... registersToSave) {
+        this.registersSaved = registersToSave;
+        this.saveSize = registersToSave.length * target.wordSize;
+
+        // align to code size
+        int entryCodeOffset = runtime.codeOffset();
+        if (entryCodeOffset != 0) {
+            asm.nop(entryCodeOffset);
+        }
+        asm.subq(AMD64.rsp, frameSize());
+
+        int index = 0;
+        for (CiRegister r : registersToSave) {
+            asm.movq(new CiAddress(CiKind.Word, AMD64.RSP, index * target.arch.wordSize), r);
+            index++;
+        }
+
+        tasm.setFrameSize(frameSize());
+        this.savedAllRegisters = false;
+    }
+
+    private void completeSavePrologue() {
+        CiCalleeSaveLayout csa = compiler.globalStubRegisterConfig.getCalleeSaveLayout();
+        this.saveSize = csa.size;
+        int entryCodeOffset = runtime.codeOffset();
+        if (entryCodeOffset != 0) {
+            // align to code size
+            asm.nop(entryCodeOffset);
+        }
+        asm.subq(AMD64.rsp, frameSize());
+        tasm.setFrameSize(frameSize());
+        int frameToCSA = 0;
+        asm.save(csa, frameToCSA);
+        this.savedAllRegisters = true;
+    }
+
+    private void epilogue() {
+        assert registerRestoreEpilogueOffset == -1;
+        registerRestoreEpilogueOffset = asm.codeBuffer.position();
+
+        if (savedAllRegisters) {
+            CiCalleeSaveLayout csa = compiler.globalStubRegisterConfig.getCalleeSaveLayout();
+            int frameToCSA = 0;
+            asm.restore(csa, frameToCSA);
+        } else {
+            // saved only select registers
+            for (int index = 0; index < registersSaved.length; index++) {
+                CiRegister r = registersSaved[index];
+                asm.movq(r, new CiAddress(CiKind.Word, AMD64.RSP, index * target.wordSize));
+            }
+            registersSaved = null;
+        }
+
+        // Restore rsp
+        asm.addq(AMD64.rsp, frameSize());
+        asm.ret(0);
+    }
+
+    private int frameSize() {
+        return target.alignFrameSize(saveSize);
+    }
+
+    private void forwardRuntimeCall(CiRuntimeCall call) {
+        // Load arguments
+        CiCallingConvention cc = compiler.globalStubRegisterConfig.getCallingConvention(RuntimeCall, call.arguments, target, false);
+        for (int i = 0; i < cc.locations.length; ++i) {
+            CiValue location = cc.locations[i];
+            loadArgument(i, location.asRegister());
+        }
+
+        // Call to the runtime
+        int before = asm.codeBuffer.position();
+        asm.call();
+        int after = asm.codeBuffer.position();
+        tasm.recordDirectCall(before, after, call, null);
+
+        if (call.resultKind != CiKind.Void) {
+            CiRegister returnRegister = compiler.globalStubRegisterConfig.getReturnRegister(call.resultKind);
+            this.storeArgument(0, returnRegister);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRAssembler.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,2245 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.target.amd64;
+
+import static com.sun.cri.bytecode.Bytecodes.*;
+import static com.sun.cri.ci.CiCallingConvention.Type.*;
+import static com.sun.cri.ci.CiRegister.*;
+import static com.sun.cri.ci.CiValue.*;
+import static java.lang.Double.*;
+import static java.lang.Float.*;
+
+import java.util.*;
+
+import com.oracle.max.asm.*;
+import com.oracle.max.asm.target.amd64.*;
+import com.oracle.max.asm.target.amd64.AMD64Assembler.*;
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.gen.LIRGenerator.*;
+import com.oracle.max.graal.compiler.globalstub.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.lir.*;
+import com.oracle.max.graal.compiler.lir.FrameMap.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ci.CiAddress.*;
+import com.sun.cri.ci.CiTargetMethod.*;
+import com.sun.cri.xir.*;
+import com.sun.cri.xir.CiXirAssembler.*;
+
+/**
+ * This class implements the x86-specific code generation for LIR.
+ */
+public final class AMD64LIRAssembler extends LIRAssembler {
+
+    private static final Object[] NO_PARAMS = new Object[0];
+    private static final long NULLWORD = 0;
+    private static final CiRegister SHIFTCount = AMD64.rcx;
+
+    private static final long DoubleSignMask = 0x7FFFFFFFFFFFFFFFL;
+
+    final CiTarget target;
+    final AMD64MacroAssembler masm;
+    final int wordSize;
+    final CiRegister rscratch1;
+
+    public AMD64LIRAssembler(GraalCompilation compilation) {
+        super(compilation);
+        masm = (AMD64MacroAssembler) asm;
+        target = compilation.target;
+        wordSize = target.wordSize;
+        rscratch1 = compilation.registerConfig.getScratchRegister();
+    }
+
+    private CiAddress asAddress(CiValue value) {
+        if (value.isAddress()) {
+            return (CiAddress) value;
+        }
+        assert value.isStackSlot();
+        return compilation.frameMap().toStackAddress((CiStackSlot) value);
+    }
+
+    @Override
+    protected int initialFrameSizeInBytes() {
+        return frameMap.frameSize();
+    }
+
+    @Override
+    protected void emitReturn(CiValue result) {
+        // TODO: Consider adding safepoint polling at return!
+        masm.ret(0);
+    }
+
+    @Override
+    protected void emitMonitorAddress(int monitor, CiValue dst) {
+        CiStackSlot slot = frameMap.toMonitorBaseStackAddress(monitor);
+        masm.leaq(dst.asRegister(), new CiAddress(slot.kind, AMD64.rsp.asValue(), slot.index() * target.arch.wordSize));
+    }
+
+    @Override
+    protected void emitBreakpoint() {
+        masm.int3();
+    }
+
+    @Override
+    protected void emitStackAllocate(StackBlock stackBlock, CiValue dst) {
+        masm.leaq(dst.asRegister(), compilation.frameMap().toStackAddress(stackBlock));
+    }
+
+    private void moveRegs(CiRegister fromReg, CiRegister toReg) {
+        if (fromReg != toReg) {
+            masm.mov(toReg, fromReg);
+        }
+    }
+
+    private void swapReg(CiRegister a, CiRegister b) {
+        masm.xchgptr(a, b);
+    }
+
+    private void const2reg(CiRegister dst, int constant) {
+        // Do not optimize with an XOR as this instruction may be between
+        // a CMP and a Jcc in which case the XOR will modify the condition
+        // flags and interfere with the Jcc.
+        masm.movl(dst, constant);
+    }
+
+    private void const2reg(CiRegister dst, long constant) {
+        // Do not optimize with an XOR as this instruction may be between
+        // a CMP and a Jcc in which case the XOR will modify the condition
+        // flags and interfere with the Jcc.
+        masm.movq(dst, constant);
+    }
+
+    private void const2reg(CiRegister dst, CiConstant constant) {
+        assert constant.kind == CiKind.Object;
+        // Do not optimize with an XOR as this instruction may be between
+        // a CMP and a Jcc in which case the XOR will modify the condition
+        // flags and interfere with the Jcc.
+        if (constant.isNull()) {
+            masm.movq(dst, 0x0L);
+        } else if (target.inlineObjects) {
+            tasm.recordDataReferenceInCode(constant);
+            masm.movq(dst, 0xDEADDEADDEADDEADL);
+        } else {
+            masm.movq(dst, tasm.recordDataReferenceInCode(constant));
+        }
+    }
+
+    @Override
+    public void emitTraps() {
+        for (int i = 0; i < GraalOptions.MethodEndBreakpointGuards; ++i) {
+            masm.int3();
+        }
+    }
+
+    private void const2reg(CiRegister dst, float constant) {
+        if (constant == 0.0f) {
+            masm.xorps(dst, dst);
+        } else {
+            masm.movflt(dst, tasm.recordDataReferenceInCode(CiConstant.forFloat(constant)));
+        }
+    }
+
+    private void const2reg(CiRegister dst, double constant) {
+        if (constant == 0.0f) {
+            masm.xorpd(dst, dst);
+        } else {
+            masm.movdbl(dst, tasm.recordDataReferenceInCode(CiConstant.forDouble(constant)));
+        }
+    }
+
+    @Override
+    protected void const2reg(CiValue src, CiValue dest, LIRDebugInfo info) {
+        assert src.isConstant();
+        assert dest.isRegister();
+        CiConstant c = (CiConstant) src;
+
+        // Checkstyle: off
+        switch (c.kind) {
+            case Boolean :
+            case Byte    :
+            case Char    :
+            case Short   :
+            case Jsr     :
+            case Int     : const2reg(dest.asRegister(), c.asInt()); break;
+            case Word    :
+            case Long    : const2reg(dest.asRegister(), c.asLong()); break;
+            case Object  : const2reg(dest.asRegister(), c); break;
+            case Float   : const2reg(asXmmFloatReg(dest), c.asFloat()); break;
+            case Double  : const2reg(asXmmDoubleReg(dest), c.asDouble()); break;
+            default      : throw Util.shouldNotReachHere();
+        }
+        // Checkstyle: on
+    }
+
+    @Override
+    protected void const2stack(CiValue src, CiValue dst) {
+        assert src.isConstant();
+        assert dst.isStackSlot();
+        CiStackSlot slot = (CiStackSlot) dst;
+        CiConstant c = (CiConstant) src;
+
+        // Checkstyle: off
+        switch (c.kind) {
+            case Boolean :
+            case Byte    :
+            case Char    :
+            case Short   :
+            case Jsr     :
+            case Int     : masm.movl(frameMap.toStackAddress(slot), c.asInt()); break;
+            case Float   : masm.movl(frameMap.toStackAddress(slot), floatToRawIntBits(c.asFloat())); break;
+            case Object  : movoop(frameMap.toStackAddress(slot), c); break;
+            case Long    : masm.mov64(frameMap.toStackAddress(slot), c.asLong()); break;
+            case Double  : masm.mov64(frameMap.toStackAddress(slot), doubleToRawLongBits(c.asDouble())); break;
+            default      : throw Util.shouldNotReachHere("Unknown constant kind for const2stack: " + c.kind);
+        }
+        // Checkstyle: on
+    }
+
+    @Override
+    protected void const2mem(CiValue src, CiValue dst, CiKind kind, LIRDebugInfo info) {
+        assert src.isConstant();
+        assert dst.isAddress();
+        CiConstant constant = (CiConstant) src;
+        CiAddress addr = asAddress(dst);
+
+        int nullCheckHere = codePos();
+        // Checkstyle: off
+        switch (kind) {
+            case Boolean :
+            case Byte    : masm.movb(addr, constant.asInt() & 0xFF); break;
+            case Char    :
+            case Short   : masm.movw(addr, constant.asInt() & 0xFFFF); break;
+            case Jsr     :
+            case Int     : masm.movl(addr, constant.asInt()); break;
+            case Float   : masm.movl(addr, floatToRawIntBits(constant.asFloat())); break;
+            case Object  : movoop(addr, constant); break;
+            case Word:
+            case Long    : masm.movq(rscratch1, constant.asLong());
+                           nullCheckHere = codePos();
+                           masm.movq(addr, rscratch1); break;
+            case Double  : masm.movq(rscratch1, doubleToRawLongBits(constant.asDouble()));
+                           nullCheckHere = codePos();
+                           masm.movq(addr, rscratch1); break;
+            default      : throw Util.shouldNotReachHere();
+        }
+        // Checkstyle: on
+
+        if (info != null) {
+            tasm.recordImplicitException(nullCheckHere, info);
+        }
+    }
+
+    @Override
+    protected void reg2reg(CiValue src, CiValue dest) {
+        assert src.isRegister();
+        assert dest.isRegister();
+
+        if (dest.kind.isFloat()) {
+            masm.movflt(asXmmFloatReg(dest), asXmmFloatReg(src));
+        } else if (dest.kind.isDouble()) {
+            masm.movdbl(asXmmDoubleReg(dest), asXmmDoubleReg(src));
+        } else {
+            moveRegs(src.asRegister(), dest.asRegister());
+        }
+    }
+
+    @Override
+    protected void reg2stack(CiValue src, CiValue dst, CiKind kind) {
+        assert src.isRegister();
+        assert dst.isStackSlot();
+        CiAddress addr = frameMap.toStackAddress((CiStackSlot) dst);
+
+        // Checkstyle: off
+        switch (src.kind) {
+            case Boolean :
+            case Byte    :
+            case Char    :
+            case Short   :
+            case Jsr     :
+            case Int     : masm.movl(addr, src.asRegister()); break;
+            case Object  :
+            case Word    :
+            case Long    : masm.movq(addr, src.asRegister()); break;
+            case Float   : masm.movflt(addr, asXmmFloatReg(src)); break;
+            case Double  : masm.movsd(addr, asXmmDoubleReg(src)); break;
+            default      : throw Util.shouldNotReachHere();
+        }
+        // Checkstyle: on
+    }
+
+    @Override
+    protected void reg2mem(CiValue src, CiValue dest, CiKind kind, LIRDebugInfo info, boolean unaligned) {
+        CiAddress toAddr = (CiAddress) dest;
+
+        if (info != null) {
+            tasm.recordImplicitException(codePos(), info);
+        }
+
+        // Checkstyle: off
+        switch (kind) {
+            case Float   : masm.movflt(toAddr, asXmmFloatReg(src)); break;
+            case Double  : masm.movsd(toAddr, asXmmDoubleReg(src)); break;
+            case Jsr     :
+            case Int     : masm.movl(toAddr, src.asRegister()); break;
+            case Long    :
+            case Word    :
+            case Object  : masm.movq(toAddr, src.asRegister()); break;
+            case Char    :
+            case Short   : masm.movw(toAddr, src.asRegister()); break;
+            case Byte    :
+            case Boolean : masm.movb(toAddr, src.asRegister()); break;
+            default      : throw Util.shouldNotReachHere();
+        }
+        // Checkstyle: on
+    }
+
+    private static CiRegister asXmmFloatReg(CiValue src) {
+        assert src.kind.isFloat() : "must be float, actual kind: " + src.kind;
+        CiRegister result = src.asRegister();
+        assert result.isFpu() : "must be xmm, actual type: " + result;
+        return result;
+    }
+
+    @Override
+    protected void stack2reg(CiValue src, CiValue dest, CiKind kind) {
+        assert src.isStackSlot();
+        assert dest.isRegister();
+
+        CiAddress addr = frameMap.toStackAddress((CiStackSlot) src);
+
+        // Checkstyle: off
+        switch (dest.kind) {
+            case Boolean :
+            case Byte    :
+            case Char    :
+            case Short   :
+            case Jsr     :
+            case Int     : masm.movl(dest.asRegister(), addr); break;
+            case Object  :
+            case Word    :
+            case Long    : masm.movq(dest.asRegister(), addr); break;
+            case Float   : masm.movflt(asXmmFloatReg(dest), addr); break;
+            case Double  : masm.movdbl(asXmmDoubleReg(dest), addr); break;
+            default      : throw Util.shouldNotReachHere();
+        }
+        // Checkstyle: on
+    }
+
+    @Override
+    protected void mem2mem(CiValue src, CiValue dest, CiKind kind) {
+        if (dest.kind.isInt()) {
+            masm.pushl((CiAddress) src);
+            masm.popl((CiAddress) dest);
+        } else {
+            masm.pushptr((CiAddress) src);
+            masm.popptr((CiAddress) dest);
+        }
+    }
+
+    @Override
+    protected void mem2stack(CiValue src, CiValue dest, CiKind kind) {
+        if (dest.kind.isInt()) {
+            masm.pushl((CiAddress) src);
+            masm.popl(frameMap.toStackAddress((CiStackSlot) dest));
+        } else {
+            masm.pushptr((CiAddress) src);
+            masm.popptr(frameMap.toStackAddress((CiStackSlot) dest));
+        }
+    }
+
+    @Override
+    protected void stack2stack(CiValue src, CiValue dest, CiKind kind) {
+        if (src.kind.isInt()) {
+            masm.pushl(frameMap.toStackAddress((CiStackSlot) src));
+            masm.popl(frameMap.toStackAddress((CiStackSlot) dest));
+        } else {
+            masm.pushptr(frameMap.toStackAddress((CiStackSlot) src));
+            masm.popptr(frameMap.toStackAddress((CiStackSlot) dest));
+        }
+    }
+
+    @Override
+    protected void mem2reg(CiValue src, CiValue dest, CiKind kind, LIRDebugInfo info, boolean unaligned) {
+        assert src.isAddress();
+        assert dest.isRegister() : "dest=" + dest;
+
+        CiAddress addr = (CiAddress) src;
+        if (info != null) {
+            tasm.recordImplicitException(codePos(), info);
+        }
+
+        // Checkstyle: off
+        switch (kind) {
+            case Float   : masm.movflt(asXmmFloatReg(dest), addr); break;
+            case Double  : masm.movdbl(asXmmDoubleReg(dest), addr); break;
+            case Object  : masm.movq(dest.asRegister(), addr); break;
+            case Int     : masm.movslq(dest.asRegister(), addr); break;
+            case Word    :
+            case Long    : masm.movq(dest.asRegister(), addr); break;
+            case Boolean :
+            case Byte    : masm.movsxb(dest.asRegister(), addr); break;
+            case Char    : masm.movzxl(dest.asRegister(), addr); break;
+            case Short   : masm.movswl(dest.asRegister(), addr); break;
+            default      : throw Util.shouldNotReachHere();
+        }
+        // Checkstyle: on
+    }
+
+    @Override
+    protected void emitReadPrefetch(CiValue src) {
+        CiAddress addr = (CiAddress) src;
+        // Checkstyle: off
+        switch (GraalOptions.ReadPrefetchInstr) {
+            case 0  : masm.prefetchnta(addr); break;
+            case 1  : masm.prefetcht0(addr); break;
+            case 2  : masm.prefetcht2(addr); break;
+            default : throw Util.shouldNotReachHere();
+        }
+        // Checkstyle: on
+    }
+
+    @Override
+    protected void emitOp3(LIROp3 op) {
+        // Checkstyle: off
+        switch (op.code) {
+            case Idiv  :
+            case Irem  : arithmeticIdiv(op.code, op.opr1(), op.opr2(), op.result(), op.info); break;
+            case Ldiv  :
+            case Lrem  : arithmeticLdiv(op.code, op.opr1(), op.opr2(), op.result(), op.info); break;
+            case Wdiv  :
+            case Wdivi :
+            case Wrem  :
+            case Wremi : arithmeticWdiv(op.code, op.opr1(), op.opr2(), op.result(), op.info); break;
+            default    : throw Util.shouldNotReachHere();
+        }
+        // Checkstyle: on
+    }
+
+    private boolean assertEmitBranch(LIRBranch op) {
+        assert op.block() == null || op.block().label() == op.label() : "wrong label";
+        return true;
+    }
+
+    private boolean assertEmitTableSwitch(LIRTableSwitch op) {
+        assert op.defaultTarget != null;
+        return true;
+    }
+
+    @Override
+    protected void emitTableSwitch(LIRTableSwitch op) {
+
+        assert assertEmitTableSwitch(op);
+
+        CiRegister value = op.value().asRegister();
+        final Buffer buf = masm.codeBuffer;
+
+        // Compare index against jump table bounds
+        int highKey = op.lowKey + op.targets.length - 1;
+        if (op.lowKey != 0) {
+            // subtract the low value from the switch value
+            masm.subl(value, op.lowKey);
+            masm.cmpl(value, highKey - op.lowKey);
+        } else {
+            masm.cmpl(value, highKey);
+        }
+
+        // Jump to default target if index is not within the jump table
+        masm.jcc(ConditionFlag.above, op.defaultTarget.label());
+
+        // Set scratch to address of jump table
+        int leaPos = buf.position();
+        buf.putMark();
+        masm.leaq(rscratch1, new CiAddress(CiKind.Word, InstructionRelative.asValue(), 0));
+
+        // Load jump table entry into scratch and jump to it
+        masm.movslq(value, new CiAddress(CiKind.Int, rscratch1.asValue(), value.asValue(), Scale.Times4, 0));
+        masm.addq(rscratch1, value);
+        masm.jmp(rscratch1);
+
+        // Inserting padding so that jump table address is 4-byte aligned
+        if ((buf.position() & 0x3) != 0) {
+            masm.nop(4 - (buf.position() & 0x3));
+        }
+
+        // Patch LEA instruction above now that we know the position of the jump table
+        int jumpTablePos = buf.position();
+        buf.setPosition(leaPos);
+        buf.putMark();
+        masm.leaq(rscratch1, new CiAddress(CiKind.Word, InstructionRelative.asValue(), jumpTablePos - leaPos));
+        buf.setPosition(jumpTablePos);
+
+        // Emit jump table entries
+        for (LIRBlock target : op.targets) {
+            Label label = target.label();
+            int offsetToJumpTableBase = buf.position() - jumpTablePos;
+            if (label.isBound()) {
+                int imm32 = label.position() - jumpTablePos;
+                buf.emitInt(imm32);
+            } else {
+                label.addPatchAt(buf.position());
+
+                buf.emitByte(0); // psuedo-opcode for jump table entry
+                buf.emitShort(offsetToJumpTableBase);
+                buf.emitByte(0); // padding to make jump table entry 4 bytes wide
+            }
+        }
+
+        JumpTable jt = new JumpTable(jumpTablePos, op.lowKey, highKey, 4);
+        tasm.targetMethod.addAnnotation(jt);
+    }
+
+    @Override
+    protected void emitBranch(LIRBranch op) {
+
+        assert assertEmitBranch(op);
+
+        if (op.cond() == Condition.TRUE) {
+            if (op.info != null) {
+                int codePos = codePos();
+                if (codePos <= tasm.lastSafepointPos()) {
+                    masm.nop();
+                }
+                tasm.recordImplicitException(codePos(), op.info);
+            }
+            masm.jmp(op.label());
+        } else {
+            ConditionFlag acond = ConditionFlag.zero;
+            Label unorderedLabel = null;
+            if (op.code == LIROpcode.CondFloatBranch) {
+                if (op.unorderedBlock() == null) {
+                    unorderedLabel = new Label();
+                } else {
+                    unorderedLabel = op.unorderedBlock().label;
+                }
+                masm.jcc(ConditionFlag.parity, unorderedLabel);
+                // Checkstyle: off
+                switch (op.cond()) {
+                    case EQ : acond = ConditionFlag.equal; break;
+                    case NE : acond = ConditionFlag.notEqual; break;
+                    case LT : acond = ConditionFlag.below; break;
+                    case LE : acond = ConditionFlag.belowEqual; break;
+                    case GE : acond = ConditionFlag.aboveEqual; break;
+                    case GT : acond = ConditionFlag.above; break;
+                    default : throw Util.shouldNotReachHere();
+                }
+            } else {
+                switch (op.cond()) {
+                    case EQ : acond = ConditionFlag.equal; break;
+                    case NE : acond = ConditionFlag.notEqual; break;
+                    case LT : acond = ConditionFlag.less; break;
+                    case LE : acond = ConditionFlag.lessEqual; break;
+                    case GE : acond = ConditionFlag.greaterEqual; break;
+                    case GT : acond = ConditionFlag.greater; break;
+                    case BE : acond = ConditionFlag.belowEqual; break;
+                    case AE : acond = ConditionFlag.aboveEqual; break;
+                    case AT : acond = ConditionFlag.above; break;
+                    case BT : acond = ConditionFlag.below; break;
+                    case OF : acond = ConditionFlag.overflow; break;
+                    case NOF : acond = ConditionFlag.noOverflow; break;
+                    default : throw Util.shouldNotReachHere();
+                }
+                // Checkstyle: on
+            }
+            masm.jcc(acond, op.label());
+            if (unorderedLabel != null && op.unorderedBlock() == null) {
+                masm.bind(unorderedLabel);
+            }
+        }
+    }
+
+    @Override
+    protected void emitConvert(LIRConvert op) {
+        CiValue src = op.operand();
+        CiValue dest = op.result();
+        Label endLabel = new Label();
+        CiRegister srcRegister = src.asRegister();
+        switch (op.bytecode) {
+            case I2L:
+                masm.movslq(dest.asRegister(), srcRegister);
+                break;
+
+            case L2I:
+                moveRegs(srcRegister, dest.asRegister());
+                masm.andl(dest.asRegister(), 0xFFFFFFFF);
+                break;
+
+            case I2B:
+                moveRegs(srcRegister, dest.asRegister());
+                masm.signExtendByte(dest.asRegister());
+                break;
+
+            case I2C:
+                moveRegs(srcRegister, dest.asRegister());
+                masm.andl(dest.asRegister(), 0xFFFF);
+                break;
+
+            case I2S:
+                moveRegs(srcRegister, dest.asRegister());
+                masm.signExtendShort(dest.asRegister());
+                break;
+
+            case F2D:
+                masm.cvtss2sd(asXmmDoubleReg(dest), asXmmFloatReg(src));
+                break;
+
+            case D2F:
+                masm.cvtsd2ss(asXmmFloatReg(dest), asXmmDoubleReg(src));
+                break;
+
+            case I2F:
+                masm.cvtsi2ssl(asXmmFloatReg(dest), srcRegister);
+                break;
+            case I2D:
+                masm.cvtsi2sdl(asXmmDoubleReg(dest), srcRegister);
+                break;
+
+            case F2I: {
+                assert srcRegister.isFpu() && dest.isRegister() : "must both be XMM register (no fpu stack)";
+                masm.cvttss2sil(dest.asRegister(), srcRegister);
+                masm.cmp32(dest.asRegister(), Integer.MIN_VALUE);
+                masm.jcc(ConditionFlag.notEqual, endLabel);
+                callGlobalStub(op.globalStub, null, dest.asRegister(), src);
+                // cannot cause an exception
+                masm.bind(endLabel);
+                break;
+            }
+            case D2I: {
+                assert srcRegister.isFpu() && dest.isRegister() : "must both be XMM register (no fpu stack)";
+                masm.cvttsd2sil(dest.asRegister(), asXmmDoubleReg(src));
+                masm.cmp32(dest.asRegister(), Integer.MIN_VALUE);
+                masm.jcc(ConditionFlag.notEqual, endLabel);
+                callGlobalStub(op.globalStub, null, dest.asRegister(), src);
+                // cannot cause an exception
+                masm.bind(endLabel);
+                break;
+            }
+            case L2F:
+                masm.cvtsi2ssq(asXmmFloatReg(dest), srcRegister);
+                break;
+
+            case L2D:
+                masm.cvtsi2sdq(asXmmDoubleReg(dest), srcRegister);
+                break;
+
+            case F2L: {
+                assert srcRegister.isFpu() && dest.kind.isLong() : "must both be XMM register (no fpu stack)";
+                masm.cvttss2siq(dest.asRegister(), asXmmFloatReg(src));
+                masm.movq(rscratch1, java.lang.Long.MIN_VALUE);
+                masm.cmpq(dest.asRegister(), rscratch1);
+                masm.jcc(ConditionFlag.notEqual, endLabel);
+                callGlobalStub(op.globalStub, null, dest.asRegister(), src);
+                masm.bind(endLabel);
+                break;
+            }
+
+            case D2L: {
+                assert srcRegister.isFpu() && dest.kind.isLong() : "must both be XMM register (no fpu stack)";
+                masm.cvttsd2siq(dest.asRegister(), asXmmDoubleReg(src));
+                masm.movq(rscratch1, java.lang.Long.MIN_VALUE);
+                masm.cmpq(dest.asRegister(), rscratch1);
+                masm.jcc(ConditionFlag.notEqual, endLabel);
+                callGlobalStub(op.globalStub, null, dest.asRegister(), src);
+                masm.bind(endLabel);
+                break;
+            }
+
+            case MOV_I2F:
+                masm.movdl(asXmmFloatReg(dest), srcRegister);
+                break;
+
+            case MOV_L2D:
+                masm.movdq(asXmmDoubleReg(dest), srcRegister);
+                break;
+
+            case MOV_F2I:
+                masm.movdl(dest.asRegister(), asXmmFloatReg(src));
+                break;
+
+            case MOV_D2L:
+                masm.movdq(dest.asRegister(), asXmmDoubleReg(src));
+                break;
+
+            default:
+                throw Util.shouldNotReachHere();
+        }
+    }
+
+    @Override
+    protected void emitCompareAndSwap(LIRCompareAndSwap op) {
+        CiAddress address = new CiAddress(CiKind.Object, op.address(), 0);
+        CiRegister newval = op.newValue().asRegister();
+        CiRegister cmpval = op.expectedValue().asRegister();
+        assert cmpval == AMD64.rax : "wrong register";
+        assert newval != null : "new val must be register";
+        assert cmpval != newval : "cmp and new values must be in different registers";
+        assert cmpval != address.base() : "cmp and addr must be in different registers";
+        assert newval != address.base() : "new value and addr must be in different registers";
+        assert cmpval != address.index() : "cmp and addr must be in different registers";
+        assert newval != address.index() : "new value and addr must be in different registers";
+        if (compilation.target.isMP) {
+            masm.lock();
+        }
+        if (op.code == LIROpcode.CasInt) {
+            masm.cmpxchgl(newval, address);
+        } else {
+            assert op.code == LIROpcode.CasObj || op.code == LIROpcode.CasLong || op.code == LIROpcode.CasWord;
+            masm.cmpxchgq(newval, address);
+        }
+    }
+
+    @Override
+    protected void emitConditionalMove(Condition condition, CiValue opr1, CiValue opr2, CiValue result) {
+        ConditionFlag acond;
+        ConditionFlag ncond;
+        switch (condition) {
+            case EQ:
+                acond = ConditionFlag.equal;
+                ncond = ConditionFlag.notEqual;
+                break;
+            case NE:
+                acond = ConditionFlag.notEqual;
+                ncond = ConditionFlag.equal;
+                break;
+            case LT:
+                acond = ConditionFlag.less;
+                ncond = ConditionFlag.greaterEqual;
+                break;
+            case LE:
+                acond = ConditionFlag.lessEqual;
+                ncond = ConditionFlag.greater;
+                break;
+            case GE:
+                acond = ConditionFlag.greaterEqual;
+                ncond = ConditionFlag.less;
+                break;
+            case GT:
+                acond = ConditionFlag.greater;
+                ncond = ConditionFlag.lessEqual;
+                break;
+            case BE:
+                acond = ConditionFlag.belowEqual;
+                ncond = ConditionFlag.above;
+                break;
+            case BT:
+                acond = ConditionFlag.below;
+                ncond = ConditionFlag.aboveEqual;
+                break;
+            case AE:
+                acond = ConditionFlag.aboveEqual;
+                ncond = ConditionFlag.below;
+                break;
+            case AT:
+                acond = ConditionFlag.above;
+                ncond = ConditionFlag.belowEqual;
+                break;
+            default:
+                throw Util.shouldNotReachHere();
+        }
+
+        CiValue def = opr1; // assume left operand as default
+        CiValue other = opr2;
+
+        if (opr2.isRegister() && opr2.asRegister() == result.asRegister()) {
+            // if the right operand is already in the result register, then use it as the default
+            def = opr2;
+            other = opr1;
+            // and flip the condition
+            ConditionFlag tcond = acond;
+            acond = ncond;
+            ncond = tcond;
+        }
+
+        if (def.isRegister()) {
+            reg2reg(def, result);
+        } else if (def.isStackSlot()) {
+            stack2reg(def, result, result.kind);
+        } else {
+            assert def.isConstant();
+            const2reg(def, result, null);
+        }
+
+        if (!other.isConstant()) {
+            // optimized version that does not require a branch
+            if (other.isRegister()) {
+                assert other.asRegister() != result.asRegister() : "other already overwritten by previous move";
+                if (other.kind.isInt()) {
+                    masm.cmovq(ncond, result.asRegister(), other.asRegister());
+                } else {
+                    masm.cmovq(ncond, result.asRegister(), other.asRegister());
+                }
+            } else {
+                assert other.isStackSlot();
+                CiStackSlot otherSlot = (CiStackSlot) other;
+                if (other.kind.isInt()) {
+                    masm.cmovl(ncond, result.asRegister(), frameMap.toStackAddress(otherSlot));
+                } else {
+                    masm.cmovq(ncond, result.asRegister(), frameMap.toStackAddress(otherSlot));
+                }
+            }
+
+        } else {
+            // conditional move not available, use emit a branch and move
+            Label skip = new Label();
+            masm.jcc(acond, skip);
+            if (other.isRegister()) {
+                reg2reg(other, result);
+            } else if (other.isStackSlot()) {
+                stack2reg(other, result, result.kind);
+            } else {
+                assert other.isConstant();
+                const2reg(other, result, null);
+            }
+            masm.bind(skip);
+        }
+    }
+
+    @Override
+    protected void emitArithOp(LIROpcode code, CiValue left, CiValue right, CiValue dest, LIRDebugInfo info) {
+        assert info == null : "should never be used :  idiv/irem and ldiv/lrem not handled by this method";
+        assert Util.archKindsEqual(left.kind, right.kind) || (left.kind == CiKind.Word && right.kind == CiKind.Int) : code.toString() + " left arch is " + left.kind + " and right arch is " +  right.kind;
+        assert left.equals(dest) : "left and dest must be equal";
+        CiKind kind = left.kind;
+
+        // Checkstyle: off
+        if (left.isRegister()) {
+            CiRegister lreg = left.asRegister();
+
+            if (right.isRegister()) {
+                // register - register
+                CiRegister rreg = right.asRegister();
+                if (kind.isInt()) {
+                    switch (code) {
+                        case Add : masm.addl(lreg, rreg); break;
+                        case Sub : masm.subl(lreg, rreg); break;
+                        case Mul : masm.imull(lreg, rreg); break;
+                        default  : throw Util.shouldNotReachHere();
+                    }
+                } else if (kind.isFloat()) {
+                    assert rreg.isFpu() : "must be xmm";
+                    switch (code) {
+                        case Add : masm.addss(lreg, rreg); break;
+                        case Sub : masm.subss(lreg, rreg); break;
+                        case Mul : masm.mulss(lreg, rreg); break;
+                        case Div : masm.divss(lreg, rreg); break;
+                        default  : throw Util.shouldNotReachHere();
+                    }
+                } else if (kind.isDouble()) {
+                    assert rreg.isFpu();
+                    switch (code) {
+                        case Add : masm.addsd(lreg, rreg); break;
+                        case Sub : masm.subsd(lreg, rreg); break;
+                        case Mul : masm.mulsd(lreg, rreg); break;
+                        case Div : masm.divsd(lreg, rreg); break;
+                        default  : throw Util.shouldNotReachHere();
+                    }
+                } else {
+                    assert target.sizeInBytes(kind) == 8;
+                    switch (code) {
+                        case Add : masm.addq(lreg, rreg); break;
+                        case Sub : masm.subq(lreg, rreg); break;
+                        case Mul : masm.imulq(lreg, rreg);  break;
+                        default  : throw Util.shouldNotReachHere();
+                    }
+                }
+            } else {
+                if (kind.isInt()) {
+                    if (right.isStackSlot()) {
+                        // register - stack
+                        CiAddress raddr = frameMap.toStackAddress(((CiStackSlot) right));
+                        switch (code) {
+                            case Add : masm.addl(lreg, raddr); break;
+                            case Sub : masm.subl(lreg, raddr); break;
+                            default  : throw Util.shouldNotReachHere();
+                        }
+                    } else if (right.isConstant()) {
+                        // register - constant
+                        assert kind.isInt();
+                        int delta = ((CiConstant) right).asInt();
+                        switch (code) {
+                            case Add : masm.incrementl(lreg, delta); break;
+                            case Sub : masm.decrementl(lreg, delta); break;
+                            default  : throw Util.shouldNotReachHere();
+                        }
+                    }
+                } else if (kind.isFloat()) {
+                    // register - stack/constant
+                    CiAddress raddr;
+                    if (right.isStackSlot()) {
+                        raddr = frameMap.toStackAddress(((CiStackSlot) right));
+                    } else {
+                        assert right.isConstant();
+                        raddr = tasm.recordDataReferenceInCode(CiConstant.forFloat(((CiConstant) right).asFloat()));
+                    }
+                    switch (code) {
+                        case Add : masm.addss(lreg, raddr); break;
+                        case Sub : masm.subss(lreg, raddr); break;
+                        case Mul : masm.mulss(lreg, raddr); break;
+                        case Div : masm.divss(lreg, raddr); break;
+                        default  : throw Util.shouldNotReachHere();
+                    }
+                } else if (kind.isDouble()) {
+                    // register - stack/constant
+                    CiAddress raddr;
+                    if (right.isStackSlot()) {
+                        raddr = frameMap.toStackAddress(((CiStackSlot) right));
+                    } else {
+                        assert right.isConstant();
+                        raddr = tasm.recordDataReferenceInCode(CiConstant.forDouble(((CiConstant) right).asDouble()));
+                    }
+                    switch (code) {
+                        case Add : masm.addsd(lreg, raddr); break;
+                        case Sub : masm.subsd(lreg, raddr); break;
+                        case Mul : masm.mulsd(lreg, raddr); break;
+                        case Div : masm.divsd(lreg, raddr); break;
+                        default  : throw Util.shouldNotReachHere();
+                    }
+                } else {
+                    assert target.sizeInBytes(kind) == 8;
+                    if (right.isStackSlot()) {
+                        // register - stack
+                        CiAddress raddr = frameMap.toStackAddress(((CiStackSlot) right));
+                        switch (code) {
+                            case Add : masm.addq(lreg, raddr); break;
+                            case Sub : masm.subq(lreg, raddr); break;
+                            default  : throw Util.shouldNotReachHere();
+                        }
+                    } else {
+                        // register - constant
+                        assert right.isConstant();
+                        long c = ((CiConstant) right).asLong();
+                        if (NumUtil.isInt(c)) {
+                            switch (code) {
+                                case Add : masm.addq(lreg, (int) c); break;
+                                case Sub : masm.subq(lreg, (int) c); break;
+                                default  : throw Util.shouldNotReachHere();
+                            }
+                        } else {
+                            masm.movq(rscratch1, c);
+                            switch (code) {
+                                case Add : masm.addq(lreg, rscratch1); break;
+                                case Sub : masm.subq(lreg, rscratch1); break;
+                                default  : throw Util.shouldNotReachHere();
+                            }
+                        }
+                    }
+                }
+            }
+        } else {
+            assert kind.isInt();
+            CiAddress laddr = asAddress(left);
+
+            if (right.isRegister()) {
+                CiRegister rreg = right.asRegister();
+                switch (code) {
+                    case Add : masm.addl(laddr, rreg); break;
+                    case Sub : masm.subl(laddr, rreg); break;
+                    default  : throw Util.shouldNotReachHere();
+                }
+            } else {
+                assert right.isConstant();
+                int c = ((CiConstant) right).asInt();
+                switch (code) {
+                    case Add : masm.incrementl(laddr, c); break;
+                    case Sub : masm.decrementl(laddr, c); break;
+                    default  : throw Util.shouldNotReachHere();
+                }
+            }
+        }
+        // Checkstyle: on
+    }
+
+    @Override
+    protected void emitIntrinsicOp(LIROpcode code, CiValue value, CiValue unused, CiValue dest, LIROp2 op) {
+        assert value.kind.isDouble();
+        switch (code) {
+            case Abs:
+                if (asXmmDoubleReg(dest) != asXmmDoubleReg(value)) {
+                    masm.movdbl(asXmmDoubleReg(dest), asXmmDoubleReg(value));
+                }
+                masm.andpd(asXmmDoubleReg(dest), tasm.recordDataReferenceInCode(CiConstant.forLong(DoubleSignMask)));
+                break;
+
+            case Sqrt:
+                masm.sqrtsd(asXmmDoubleReg(dest), asXmmDoubleReg(value));
+                break;
+
+            default:
+                throw Util.shouldNotReachHere();
+        }
+    }
+
+    @Override
+    protected void emitLogicOp(LIROpcode code, CiValue left, CiValue right, CiValue dst) {
+        assert left.isRegister();
+        // Checkstyle: off
+        if (left.kind.isInt()) {
+            CiRegister reg = left.asRegister();
+            if (right.isConstant()) {
+                int val = ((CiConstant) right).asInt();
+                switch (code) {
+                    case LogicAnd : masm.andl(reg, val); break;
+                    case LogicOr  : masm.orl(reg, val); break;
+                    case LogicXor : masm.xorl(reg, val); break;
+                    default       : throw Util.shouldNotReachHere();
+                }
+            } else if (right.isStackSlot()) {
+                // added support for stack operands
+                CiAddress raddr = frameMap.toStackAddress(((CiStackSlot) right));
+                switch (code) {
+                    case LogicAnd : masm.andl(reg, raddr); break;
+                    case LogicOr  : masm.orl(reg, raddr); break;
+                    case LogicXor : masm.xorl(reg, raddr); break;
+                    default       : throw Util.shouldNotReachHere();
+                }
+            } else {
+                CiRegister rright = right.asRegister();
+                switch (code) {
+                    case LogicAnd : masm.andq(reg, rright); break;
+                    case LogicOr  : masm.orq(reg, rright); break;
+                    case LogicXor : masm.xorptr(reg, rright); break;
+                    default       : throw Util.shouldNotReachHere();
+                }
+            }
+            moveRegs(reg, dst.asRegister());
+        } else {
+            assert target.sizeInBytes(left.kind) == 8;
+            CiRegister lreg = left.asRegister();
+            if (right.isConstant()) {
+                CiConstant rightConstant = (CiConstant) right;
+                masm.movq(rscratch1, rightConstant.asLong());
+                switch (code) {
+                    case LogicAnd : masm.andq(lreg, rscratch1); break;
+                    case LogicOr  : masm.orq(lreg, rscratch1); break;
+                    case LogicXor : masm.xorq(lreg, rscratch1); break;
+                    default       : throw Util.shouldNotReachHere();
+                }
+            } else {
+                CiRegister rreg = right.asRegister();
+                switch (code) {
+                    case LogicAnd : masm.andq(lreg, rreg); break;
+                    case LogicOr  : masm.orq(lreg, rreg); break;
+                    case LogicXor : masm.xorptr(lreg, rreg); break;
+                    default       : throw Util.shouldNotReachHere();
+                }
+            }
+
+            CiRegister dreg = dst.asRegister();
+            moveRegs(lreg, dreg);
+        }
+        // Checkstyle: on
+    }
+
+    void arithmeticIdiv(LIROpcode code, CiValue left, CiValue right, CiValue result, LIRDebugInfo info) {
+        assert left.isRegister() : "left must be register";
+        assert right.isRegister() || right.isConstant() : "right must be register or constant";
+        assert result.isRegister() : "result must be register";
+
+        CiRegister lreg = left.asRegister();
+        CiRegister dreg = result.asRegister();
+
+        if (right.isConstant()) {
+            int divisor = ((CiConstant) right).asInt();
+            assert divisor > 0 && CiUtil.isPowerOf2(divisor) : "divisor must be power of two";
+            if (code == LIROpcode.Idiv) {
+                assert lreg == AMD64.rax : "dividend must be rax";
+                masm.cdql(); // sign extend into rdx:rax
+                if (divisor == 2) {
+                    masm.subl(lreg, AMD64.rdx);
+                } else {
+                    masm.andl(AMD64.rdx, divisor - 1);
+                    masm.addl(lreg, AMD64.rdx);
+                }
+                masm.sarl(lreg, CiUtil.log2(divisor));
+                moveRegs(lreg, dreg);
+            } else {
+                assert code == LIROpcode.Irem;
+                Label done = new Label();
+                masm.mov(dreg, lreg);
+                masm.andl(dreg, 0x80000000 | (divisor - 1));
+                masm.jcc(ConditionFlag.positive, done);
+                masm.decrementl(dreg, 1);
+                masm.orl(dreg, ~(divisor - 1));
+                masm.incrementl(dreg, 1);
+                masm.bind(done);
+            }
+        } else {
+            CiRegister rreg = right.asRegister();
+            assert lreg == AMD64.rax : "left register must be rax";
+            assert rreg != AMD64.rdx : "right register must not be rdx";
+
+            moveRegs(lreg, AMD64.rax);
+
+            Label continuation = new Label();
+
+            if (GraalOptions.GenSpecialDivChecks) {
+                // check for special case of Integer.MIN_VALUE / -1
+                Label normalCase = new Label();
+                masm.cmpl(AMD64.rax, Integer.MIN_VALUE);
+                masm.jcc(ConditionFlag.notEqual, normalCase);
+                if (code == LIROpcode.Irem) {
+                    // prepare X86Register.rdx for possible special case where remainder = 0
+                    masm.xorl(AMD64.rdx, AMD64.rdx);
+                }
+                masm.cmpl(rreg, -1);
+                masm.jcc(ConditionFlag.equal, continuation);
+
+                // handle normal case
+                masm.bind(normalCase);
+            }
+            masm.cdql();
+            int offset = masm.codeBuffer.position();
+            masm.idivl(rreg);
+
+            // normal and special case exit
+            masm.bind(continuation);
+
+            tasm.recordImplicitException(offset, info);
+            if (code == LIROpcode.Irem) {
+                moveRegs(AMD64.rdx, dreg); // result is in rdx
+            } else {
+                assert code == LIROpcode.Idiv;
+                moveRegs(AMD64.rax, dreg);
+            }
+        }
+    }
+
+    void arithmeticLdiv(LIROpcode code, CiValue left, CiValue right, CiValue result, LIRDebugInfo info) {
+        assert left.isRegister() : "left must be register";
+        assert right.isRegister() : "right must be register";
+        assert result.isRegister() : "result must be register";
+        assert result.kind.isLong();
+
+        CiRegister lreg = left.asRegister();
+        CiRegister dreg = result.asRegister();
+        CiRegister rreg = right.asRegister();
+        assert lreg == AMD64.rax : "left register must be rax";
+        assert rreg != AMD64.rdx : "right register must not be rdx";
+
+        moveRegs(lreg, AMD64.rax);
+
+        Label continuation = new Label();
+
+        if (GraalOptions.GenSpecialDivChecks) {
+            // check for special case of Long.MIN_VALUE / -1
+            Label normalCase = new Label();
+            masm.movq(AMD64.rdx, java.lang.Long.MIN_VALUE);
+            masm.cmpq(AMD64.rax, AMD64.rdx);
+            masm.jcc(ConditionFlag.notEqual, normalCase);
+            if (code == LIROpcode.Lrem) {
+                // prepare X86Register.rdx for possible special case (where remainder = 0)
+                masm.xorq(AMD64.rdx, AMD64.rdx);
+            }
+            masm.cmpl(rreg, -1);
+            masm.jcc(ConditionFlag.equal, continuation);
+
+            // handle normal case
+            masm.bind(normalCase);
+        }
+        masm.cdqq();
+        int offset = masm.codeBuffer.position();
+        masm.idivq(rreg);
+
+        // normal and special case exit
+        masm.bind(continuation);
+
+        tasm.recordImplicitException(offset, info);
+        if (code == LIROpcode.Lrem) {
+            moveRegs(AMD64.rdx, dreg);
+        } else {
+            assert code == LIROpcode.Ldiv;
+            moveRegs(AMD64.rax, dreg);
+        }
+    }
+
+    void arithmeticWdiv(LIROpcode code, CiValue left, CiValue right, CiValue result, LIRDebugInfo info) {
+        assert left.isRegister() : "left must be register";
+        assert right.isRegister() : "right must be register";
+        assert result.isRegister() : "result must be register";
+
+        CiRegister lreg = left.asRegister();
+        CiRegister dreg = result.asRegister();
+        CiRegister rreg = right.asRegister();
+        assert lreg == AMD64.rax : "left register must be rax";
+        assert rreg != AMD64.rdx : "right register must not be rdx";
+
+        // Must zero the high 64-bit word (in RDX) of the dividend
+        masm.xorq(AMD64.rdx, AMD64.rdx);
+
+        if (code == LIROpcode.Wdivi || code == LIROpcode.Wremi) {
+            // Zero the high 32 bits of the divisor
+            masm.movzxd(rreg, rreg);
+        }
+
+        moveRegs(lreg, AMD64.rax);
+
+        int offset = masm.codeBuffer.position();
+        masm.divq(rreg);
+
+        tasm.recordImplicitException(offset, info);
+        if (code == LIROpcode.Wrem || code == LIROpcode.Wremi) {
+            moveRegs(AMD64.rdx, dreg);
+        } else {
+            assert code == LIROpcode.Wdiv || code == LIROpcode.Wdivi;
+            moveRegs(AMD64.rax, dreg);
+        }
+    }
+
+    @Override
+    protected void emitCompare(Condition condition, CiValue opr1, CiValue opr2, LIROp2 op) {
+        // Checkstyle: off
+        assert Util.archKindsEqual(opr1.kind.stackKind(), opr2.kind.stackKind()) || (opr1.kind == CiKind.Word && opr2.kind == CiKind.Int) : "nonmatching stack kinds (" + condition + "): " + opr1.kind.stackKind() + "==" + opr2.kind.stackKind();
+
+        if (opr1.isConstant()) {
+            // Use scratch register
+            CiValue newOpr1 = compilation.registerConfig.getScratchRegister().asValue(opr1.kind);
+            const2reg(opr1, newOpr1, null);
+            opr1 = newOpr1;
+        }
+
+        if (opr1.isRegister()) {
+            CiRegister reg1 = opr1.asRegister();
+            if (opr2.isRegister()) {
+                // register - register
+                switch (opr1.kind) {
+                    case Boolean :
+                    case Byte    :
+                    case Char    :
+                    case Short   :
+                    case Int     : masm.cmpl(reg1, opr2.asRegister()); break;
+                    case Long    :
+                    case Word    :
+                    case Object  : masm.cmpq(reg1, opr2.asRegister()); break;
+                    case Float   : masm.ucomiss(reg1, asXmmFloatReg(opr2)); break;
+                    case Double  : masm.ucomisd(reg1, asXmmDoubleReg(opr2)); break;
+                    default      : throw Util.shouldNotReachHere(opr1.kind.toString());
+                }
+            } else if (opr2.isStackSlot()) {
+                // register - stack
+                CiStackSlot opr2Slot = (CiStackSlot) opr2;
+                switch (opr1.kind) {
+                    case Boolean :
+                    case Byte    :
+                    case Char    :
+                    case Short   :
+                    case Int     : masm.cmpl(reg1, frameMap.toStackAddress(opr2Slot)); break;
+                    case Long    :
+                    case Word    :
+                    case Object  : masm.cmpptr(reg1, frameMap.toStackAddress(opr2Slot)); break;
+                    case Float   : masm.ucomiss(reg1, frameMap.toStackAddress(opr2Slot)); break;
+                    case Double  : masm.ucomisd(reg1, frameMap.toStackAddress(opr2Slot)); break;
+                    default      : throw Util.shouldNotReachHere();
+                }
+            } else if (opr2.isConstant()) {
+                // register - constant
+                CiConstant c = (CiConstant) opr2;
+                switch (opr1.kind) {
+                    case Boolean :
+                    case Byte    :
+                    case Char    :
+                    case Short   :
+                    case Int     : masm.cmpl(reg1, c.asInt()); break;
+                    case Float   : masm.ucomiss(reg1, tasm.recordDataReferenceInCode(CiConstant.forFloat(((CiConstant) opr2).asFloat()))); break;
+                    case Double  : masm.ucomisd(reg1, tasm.recordDataReferenceInCode(CiConstant.forDouble(((CiConstant) opr2).asDouble()))); break;
+                    case Long    :
+                    case Word    : {
+                        if (c.asLong() == 0) {
+                            masm.cmpq(reg1, 0);
+                        } else {
+                            masm.movq(rscratch1, c.asLong());
+                            masm.cmpq(reg1, rscratch1);
+
+                        }
+                        break;
+                    }
+                    case Object  :  {
+                        movoop(rscratch1, c);
+                        masm.cmpq(reg1, rscratch1);
+                        break;
+                    }
+                    default      : throw Util.shouldNotReachHere();
+                }
+            } else {
+                throw Util.shouldNotReachHere();
+            }
+        } else if (opr1.isStackSlot()) {
+            CiAddress left = asAddress(opr1);
+            if (opr2.isConstant()) {
+                CiConstant right = (CiConstant) opr2;
+                // stack - constant
+                switch (opr1.kind) {
+                    case Boolean :
+                    case Byte    :
+                    case Char    :
+                    case Short   :
+                    case Int     : masm.cmpl(left, right.asInt()); break;
+                    case Long    :
+                    case Word    : assert NumUtil.isInt(right.asLong());
+                                   masm.cmpq(left, right.asInt()); break;
+                    case Object  : assert right.isNull();
+                                   masm.cmpq(left, 0); break;
+                    default      : throw Util.shouldNotReachHere();
+                }
+            } else {
+                throw Util.shouldNotReachHere("opr1=" + opr1.toString() + " opr2=" + opr2);
+            }
+
+        } else {
+            throw Util.shouldNotReachHere("opr1=" + opr1.toString() + " opr2=" + opr2);
+        }
+        // Checkstyle: on
+    }
+
+    @Override
+    protected void emitCompare2Int(LIROpcode code, CiValue left, CiValue right, CiValue dst, LIROp2 op) {
+        if (code == LIROpcode.Cmpfd2i || code == LIROpcode.Ucmpfd2i) {
+            if (left.kind.isFloat()) {
+                masm.cmpss2int(asXmmFloatReg(left), asXmmFloatReg(right), dst.asRegister(), code == LIROpcode.Ucmpfd2i);
+            } else if (left.kind.isDouble()) {
+                masm.cmpsd2int(asXmmDoubleReg(left), asXmmDoubleReg(right), dst.asRegister(), code == LIROpcode.Ucmpfd2i);
+            } else {
+                assert false : "no fpu stack";
+            }
+        } else {
+            assert code == LIROpcode.Cmpl2i;
+            CiRegister dest = dst.asRegister();
+            Label high = new Label();
+            Label done = new Label();
+            Label isEqual = new Label();
+            masm.cmpptr(left.asRegister(), right.asRegister());
+            masm.jcc(ConditionFlag.equal, isEqual);
+            masm.jcc(ConditionFlag.greater, high);
+            masm.xorptr(dest, dest);
+            masm.decrementl(dest, 1);
+            masm.jmp(done);
+            masm.bind(high);
+            masm.xorptr(dest, dest);
+            masm.incrementl(dest, 1);
+            masm.jmp(done);
+            masm.bind(isEqual);
+            masm.xorptr(dest, dest);
+            masm.bind(done);
+        }
+    }
+
+    @Override
+    protected void emitCallAlignment(LIROpcode code) {
+        if (GraalOptions.AlignCallsForPatching) {
+            // make sure that the displacement word of the call ends up word aligned
+            int offset = masm.codeBuffer.position();
+            offset += compilation.target.arch.machineCodeCallDisplacementOffset;
+            while (offset++ % wordSize != 0) {
+                masm.nop();
+            }
+        }
+    }
+
+    @Override
+    protected void emitIndirectCall(Object target, LIRDebugInfo info, CiValue callAddress) {
+        CiRegister reg = rscratch1;
+        if (callAddress.isRegister()) {
+            reg = callAddress.asRegister();
+        } else {
+            moveOp(callAddress, reg.asValue(callAddress.kind), callAddress.kind, null, false);
+        }
+        indirectCall(reg, target, info);
+    }
+
+    @Override
+    protected void emitDirectCall(Object target, LIRDebugInfo info) {
+        directCall(target, info);
+    }
+
+    @Override
+    protected void emitNativeCall(String symbol, LIRDebugInfo info, CiValue callAddress) {
+        CiRegister reg = rscratch1;
+        if (callAddress.isRegister()) {
+            reg = callAddress.asRegister();
+        } else {
+            moveOp(callAddress, reg.asValue(callAddress.kind), callAddress.kind, null, false);
+        }
+        indirectCall(reg, symbol, info);
+    }
+
+    @Override
+    protected void emitTemplateCall(CiValue address) {
+        if (address == null) {
+            directCall(null, null);
+            return;
+        }
+
+        CiRegister reg = rscratch1;
+        if (address.isRegister()) {
+            reg = address.asRegister();
+        } else {
+            moveOp(address, reg.asValue(address.kind), address.kind, null, false);
+        }
+        indirectCall(reg, null, null);
+    }
+
+    private void emitXIRShiftOp(LIROpcode code, CiValue left, CiValue count, CiValue dest) {
+        if (count.isConstant()) {
+            emitShiftOp(code, left, ((CiConstant) count).asInt(), dest);
+        } else {
+            emitShiftOp(code, left, count, dest, IllegalValue);
+        }
+    }
+
+    @Override
+    protected void emitShiftOp(LIROpcode code, CiValue left, CiValue count, CiValue dest, CiValue tmp) {
+        // optimized version for linear scan:
+        // * count must be already in ECX (guaranteed by LinearScan)
+        // * left and dest must be equal
+        // * tmp must be unused
+        assert count.asRegister() == SHIFTCount : "count must be in ECX";
+        assert left == dest : "left and dest must be equal";
+        assert tmp.isIllegal() : "wasting a register if tmp is allocated";
+        assert left.isRegister();
+
+        if (left.kind.isInt()) {
+            CiRegister value = left.asRegister();
+            assert value != SHIFTCount : "left cannot be ECX";
+
+            // Checkstyle: off
+            switch (code) {
+                case Shl  : masm.shll(value); break;
+                case Shr  : masm.sarl(value); break;
+                case Ushr : masm.shrl(value); break;
+                default   : throw Util.shouldNotReachHere();
+            }
+        } else {
+            CiRegister lreg = left.asRegister();
+            assert lreg != SHIFTCount : "left cannot be ECX";
+
+            switch (code) {
+                case Shl  : masm.shlq(lreg); break;
+                case Shr  : masm.sarq(lreg); break;
+                case Ushr : masm.shrq(lreg); break;
+                default   : throw Util.shouldNotReachHere();
+            }
+            // Checkstyle: on
+        }
+    }
+
+    @Override
+    protected void emitShiftOp(LIROpcode code, CiValue left, int count, CiValue dest) {
+        assert dest.isRegister();
+        if (dest.kind.isInt()) {
+            // first move left into dest so that left is not destroyed by the shift
+            CiRegister value = dest.asRegister();
+            count = count & 0x1F; // Java spec
+
+            moveRegs(left.asRegister(), value);
+            // Checkstyle: off
+            switch (code) {
+                case Shl  : masm.shll(value, count); break;
+                case Shr  : masm.sarl(value, count); break;
+                case Ushr : masm.shrl(value, count); break;
+                default   : throw Util.shouldNotReachHere();
+            }
+        } else {
+
+            // first move left into dest so that left is not destroyed by the shift
+            CiRegister value = dest.asRegister();
+            count = count & 0x1F; // Java spec
+
+            moveRegs(left.asRegister(), value);
+            switch (code) {
+                case Shl  : masm.shlq(value, count); break;
+                case Shr  : masm.sarq(value, count); break;
+                case Ushr : masm.shrq(value, count); break;
+                default   : throw Util.shouldNotReachHere();
+            }
+            // Checkstyle: on
+        }
+    }
+
+    @Override
+    protected void emitSignificantBitOp(boolean most, CiValue src, CiValue dst) {
+        assert dst.isRegister();
+        CiRegister result = dst.asRegister();
+        masm.xorq(result, result);
+        masm.notq(result);
+        if (src.isRegister()) {
+            CiRegister value = src.asRegister();
+            assert value != result;
+            if (most) {
+                masm.bsrq(result, value);
+            } else {
+                masm.bsfq(result, value);
+            }
+        } else {
+            CiAddress laddr = asAddress(src);
+            if (most) {
+                masm.bsrq(result, laddr);
+            } else {
+                masm.bsfq(result, laddr);
+            }
+        }
+    }
+
+    @Override
+    protected void emitAlignment() {
+        masm.align(wordSize);
+    }
+
+    @Override
+    protected void emitNegate(LIRNegate op) {
+        CiValue left = op.operand();
+        CiValue dest = op.result();
+        assert left.isRegister();
+        if (left.kind.isInt()) {
+            masm.negl(left.asRegister());
+            moveRegs(left.asRegister(), dest.asRegister());
+
+        } else if (dest.kind.isFloat()) {
+            if (asXmmFloatReg(left) != asXmmFloatReg(dest)) {
+                masm.movflt(asXmmFloatReg(dest), asXmmFloatReg(left));
+            }
+            callGlobalStub(op.globalStub, null, asXmmFloatReg(dest), dest);
+
+        } else if (dest.kind.isDouble()) {
+            if (asXmmDoubleReg(left) != asXmmDoubleReg(dest)) {
+                masm.movdbl(asXmmDoubleReg(dest), asXmmDoubleReg(left));
+            }
+
+            callGlobalStub(op.globalStub, null, asXmmDoubleReg(dest), dest);
+        } else {
+            CiRegister lreg = left.asRegister();
+            CiRegister dreg = dest.asRegister();
+            masm.movq(dreg, lreg);
+            masm.negq(dreg);
+        }
+    }
+
+    @Override
+    protected void emitLea(CiValue src, CiValue dest) {
+        CiRegister reg = dest.asRegister();
+        masm.leaq(reg, asAddress(src));
+    }
+
+    @Override
+    protected void emitNullCheck(CiValue src, LIRDebugInfo info) {
+        assert src.isRegister();
+        if (GraalOptions.NullCheckUniquePc) {
+            masm.nop();
+        }
+        tasm.recordImplicitException(codePos(), info);
+        masm.nullCheck(src.asRegister());
+    }
+
+    @Override
+    protected void emitVolatileMove(CiValue src, CiValue dest, CiKind kind, LIRDebugInfo info) {
+        assert kind == CiKind.Long : "only for volatile long fields";
+
+        if (info != null) {
+            tasm.recordImplicitException(codePos(), info);
+        }
+
+        if (src.kind.isDouble()) {
+            if (dest.isRegister()) {
+                masm.movdq(dest.asRegister(), asXmmDoubleReg(src));
+            } else if (dest.isStackSlot()) {
+                masm.movsd(frameMap.toStackAddress((CiStackSlot) dest), asXmmDoubleReg(src));
+            } else {
+                assert dest.isAddress();
+                masm.movsd((CiAddress) dest, asXmmDoubleReg(src));
+            }
+        } else {
+            assert dest.kind.isDouble();
+            if (src.isStackSlot()) {
+                masm.movdbl(asXmmDoubleReg(dest), frameMap.toStackAddress((CiStackSlot) src));
+            } else {
+                assert src.isAddress();
+                masm.movdbl(asXmmDoubleReg(dest), (CiAddress) src);
+            }
+        }
+    }
+
+    private static CiRegister asXmmDoubleReg(CiValue dest) {
+        assert dest.kind.isDouble() : "must be double XMM register";
+        CiRegister result = dest.asRegister();
+        assert result.isFpu() : "must be XMM register";
+        return result;
+    }
+
+    @Override
+    protected void emitMemoryBarriers(int barriers) {
+        masm.membar(barriers);
+    }
+
+    @Override
+    protected void doPeephole(LIRList list) {
+        // Do nothing for now
+    }
+
+    @Override
+    protected void emitXir(LIRXirInstruction instruction) {
+        XirSnippet snippet = instruction.snippet;
+
+
+        Label endLabel = null;
+        Label[] labels = new Label[snippet.template.labels.length];
+        for (int i = 0; i < labels.length; i++) {
+            labels[i] = new Label();
+            if (snippet.template.labels[i].name == XirLabel.TrueSuccessor) {
+                if (instruction.trueSuccessor() == null) {
+                    assert endLabel == null;
+                    endLabel = new Label();
+                    labels[i] = endLabel;
+                } else {
+                    labels[i] = instruction.trueSuccessor().label;
+                }
+            } else if (snippet.template.labels[i].name == XirLabel.FalseSuccessor) {
+                if (instruction.falseSuccessor() == null) {
+                    assert endLabel == null;
+                    endLabel = new Label();
+                    labels[i] = endLabel;
+                } else {
+                    labels[i] = instruction.falseSuccessor().label;
+                }
+            }
+        }
+        emitXirInstructions(instruction, snippet.template.fastPath, labels, instruction.getOperands(), snippet.marks);
+        if (endLabel != null) {
+            masm.bind(endLabel);
+        }
+
+        if (snippet.template.slowPath != null) {
+            addSlowPath(new SlowPath(instruction, labels, snippet.marks));
+        }
+    }
+
+    @Override
+    protected void emitSlowPath(SlowPath sp) {
+        int start = -1;
+        if (GraalOptions.TraceAssembler) {
+            TTY.println("Emitting slow path for XIR instruction " + sp.instruction.snippet.template.name);
+            start = masm.codeBuffer.position();
+        }
+        emitXirInstructions(sp.instruction, sp.instruction.snippet.template.slowPath, sp.labels, sp.instruction.getOperands(), sp.marks);
+        masm.nop();
+        if (GraalOptions.TraceAssembler) {
+            TTY.println("From " + start + " to " + masm.codeBuffer.position());
+        }
+    }
+
+    public void emitXirInstructions(LIRXirInstruction xir, XirInstruction[] instructions, Label[] labels, CiValue[] operands, Map<XirMark, Mark> marks) {
+        LIRDebugInfo info = xir == null ? null : xir.info;
+        LIRDebugInfo infoAfter = xir == null ? null : xir.infoAfter;
+
+        for (XirInstruction inst : instructions) {
+            switch (inst.op) {
+                case Add:
+                    emitArithOp(LIROpcode.Add, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index], null);
+                    break;
+
+                case Sub:
+                    emitArithOp(LIROpcode.Sub, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index], null);
+                    break;
+
+                case Div:
+                    if (inst.kind == CiKind.Int) {
+                        arithmeticIdiv(LIROpcode.Idiv, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index], null);
+                    } else {
+                        emitArithOp(LIROpcode.Div, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index], null);
+                    }
+                    break;
+
+                case Mul:
+                    emitArithOp(LIROpcode.Mul, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index], null);
+                    break;
+
+                case Mod:
+                    if (inst.kind == CiKind.Int) {
+                        arithmeticIdiv(LIROpcode.Irem, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index], null);
+                    } else {
+                        emitArithOp(LIROpcode.Rem, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index], null);
+                    }
+                    break;
+
+                case Shl:
+                    emitXIRShiftOp(LIROpcode.Shl, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index]);
+                    break;
+
+                case Sar:
+                    emitXIRShiftOp(LIROpcode.Shr, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index]);
+                    break;
+
+                case Shr:
+                    emitXIRShiftOp(LIROpcode.Ushr, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index]);
+                    break;
+
+                case And:
+                    emitLogicOp(LIROpcode.LogicAnd, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index]);
+                    break;
+
+                case Or:
+                    emitLogicOp(LIROpcode.LogicOr, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index]);
+                    break;
+
+                case Xor:
+                    emitLogicOp(LIROpcode.LogicXor, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index]);
+                    break;
+
+                case Mov: {
+                    CiValue result = operands[inst.result.index];
+                    CiValue source = operands[inst.x().index];
+                    moveOp(source, result, result.kind, null, false);
+                    break;
+                }
+
+                case PointerLoad: {
+                    if ((Boolean) inst.extra && info != null) {
+                        tasm.recordImplicitException(codePos(), info);
+                    }
+
+                    CiValue result = operands[inst.result.index];
+                    CiValue pointer = operands[inst.x().index];
+                    CiRegisterValue register = assureInRegister(pointer);
+                    moveOp(new CiAddress(inst.kind, register, 0), result, inst.kind, null, false);
+                    break;
+                }
+
+                case PointerStore: {
+                    if ((Boolean) inst.extra && info != null) {
+                        tasm.recordImplicitException(codePos(), info);
+                    }
+
+                    CiValue value = operands[inst.y().index];
+                    CiValue pointer = operands[inst.x().index];
+                    assert pointer.isVariableOrRegister();
+                    moveOp(value, new CiAddress(inst.kind, pointer, 0), inst.kind, null, false);
+                    break;
+                }
+
+                case PointerLoadDisp: {
+                    CiXirAssembler.AddressAccessInformation addressInformation = (CiXirAssembler.AddressAccessInformation) inst.extra;
+                    boolean canTrap = addressInformation.canTrap;
+
+                    CiAddress.Scale scale = addressInformation.scale;
+                    int displacement = addressInformation.disp;
+
+                    CiValue result = operands[inst.result.index];
+                    CiValue pointer = operands[inst.x().index];
+                    CiValue index = operands[inst.y().index];
+
+                    pointer = assureInRegister(pointer);
+                    assert pointer.isVariableOrRegister();
+
+                    CiValue src = null;
+                    if (index.isConstant()) {
+                        assert index.kind == CiKind.Int;
+                        CiConstant constantIndex = (CiConstant) index;
+                        src = new CiAddress(inst.kind, pointer, constantIndex.asInt() * scale.value + displacement);
+                    } else {
+                        src = new CiAddress(inst.kind, pointer, index, scale, displacement);
+                    }
+
+                    moveOp(src, result, inst.kind, canTrap ? info : null, false);
+                    break;
+                }
+
+                case LoadEffectiveAddress: {
+                    CiXirAssembler.AddressAccessInformation addressInformation = (CiXirAssembler.AddressAccessInformation) inst.extra;
+
+                    CiAddress.Scale scale = addressInformation.scale;
+                    int displacement = addressInformation.disp;
+
+                    CiValue result = operands[inst.result.index];
+                    CiValue pointer = operands[inst.x().index];
+                    CiValue index = operands[inst.y().index];
+
+                    pointer = assureInRegister(pointer);
+                    assert pointer.isVariableOrRegister();
+                    CiValue src = new CiAddress(CiKind.Illegal, pointer, index, scale, displacement);
+                    emitLea(src, result);
+                    break;
+                }
+
+                case PointerStoreDisp: {
+                    CiXirAssembler.AddressAccessInformation addressInformation = (CiXirAssembler.AddressAccessInformation) inst.extra;
+                    boolean canTrap = addressInformation.canTrap;
+
+                    CiAddress.Scale scale = addressInformation.scale;
+                    int displacement = addressInformation.disp;
+
+                    CiValue value = operands[inst.z().index];
+                    CiValue pointer = operands[inst.x().index];
+                    CiValue index = operands[inst.y().index];
+
+                    pointer = assureInRegister(pointer);
+                    assert pointer.isVariableOrRegister();
+
+                    CiValue dst;
+                    if (index.isConstant()) {
+                        assert index.kind == CiKind.Int;
+                        CiConstant constantIndex = (CiConstant) index;
+                        dst = new CiAddress(inst.kind, pointer, IllegalValue, scale, constantIndex.asInt() * scale.value + displacement);
+                    } else {
+                        dst = new CiAddress(inst.kind, pointer, index, scale, displacement);
+                    }
+
+                    moveOp(value, dst, inst.kind, canTrap ? info : null, false);
+                    break;
+                }
+
+                case RepeatMoveBytes:
+                    assert operands[inst.x().index].asRegister().equals(AMD64.rsi) : "wrong input x: " + operands[inst.x().index];
+                    assert operands[inst.y().index].asRegister().equals(AMD64.rdi) : "wrong input y: " + operands[inst.y().index];
+                    assert operands[inst.z().index].asRegister().equals(AMD64.rcx) : "wrong input z: " + operands[inst.z().index];
+                    masm.repeatMoveBytes();
+                    break;
+
+                case RepeatMoveWords:
+                    assert operands[inst.x().index].asRegister().equals(AMD64.rsi) : "wrong input x: " + operands[inst.x().index];
+                    assert operands[inst.y().index].asRegister().equals(AMD64.rdi) : "wrong input y: " + operands[inst.y().index];
+                    assert operands[inst.z().index].asRegister().equals(AMD64.rcx) : "wrong input z: " + operands[inst.z().index];
+                    masm.repeatMoveWords();
+                    break;
+
+                case PointerCAS:
+
+                    if ((Boolean) inst.extra && info != null) {
+                        tasm.recordImplicitException(codePos(), info);
+                    }
+                    assert operands[inst.x().index].asRegister().equals(AMD64.rax) : "wrong input x: " + operands[inst.x().index];
+
+                    CiValue exchangedVal = operands[inst.y().index];
+                    CiValue exchangedAddress = operands[inst.x().index];
+                    CiRegisterValue pointerRegister = assureInRegister(exchangedAddress);
+                    CiAddress addr = new CiAddress(CiKind.Word, pointerRegister);
+                    masm.cmpxchgq(exchangedVal.asRegister(), addr);
+
+                    break;
+
+                case CallStub: {
+                    XirTemplate stubId = (XirTemplate) inst.extra;
+                    CiRegister result = CiRegister.None;
+                    if (inst.result != null) {
+                        result = operands[inst.result.index].asRegister();
+                    }
+                    CiValue[] args = new CiValue[inst.arguments.length];
+                    for (int i = 0; i < args.length; i++) {
+                        args[i] = operands[inst.arguments[i].index];
+                    }
+                    callGlobalStub(stubId, info, result, args);
+                    break;
+                }
+                case CallRuntime: {
+                    CiKind[] signature = new CiKind[inst.arguments.length];
+                    for (int i = 0; i < signature.length; i++) {
+                        signature[i] = inst.arguments[i].kind;
+                    }
+
+                    CiCallingConvention cc = frameMap.getCallingConvention(signature, RuntimeCall);
+                    for (int i = 0; i < inst.arguments.length; i++) {
+                        CiValue argumentLocation = cc.locations[i];
+                        CiValue argumentSourceLocation = operands[inst.arguments[i].index];
+                        if (argumentLocation != argumentSourceLocation) {
+                            moveOp(argumentSourceLocation, argumentLocation, argumentLocation.kind, null, false);
+                        }
+                    }
+
+                    RuntimeCallInformation runtimeCallInformation = (RuntimeCallInformation) inst.extra;
+                    directCall(runtimeCallInformation.target, (runtimeCallInformation.useInfoAfter) ? infoAfter : info);
+
+                    if (inst.result != null && inst.result.kind != CiKind.Illegal && inst.result.kind != CiKind.Void) {
+                        CiRegister returnRegister = compilation.registerConfig.getReturnRegister(inst.result.kind);
+                        CiValue resultLocation = returnRegister.asValue(inst.result.kind.stackKind());
+                        moveOp(resultLocation, operands[inst.result.index], inst.result.kind.stackKind(), null, false);
+                    }
+                    break;
+                }
+                case Jmp: {
+                    if (inst.extra instanceof XirLabel) {
+                        Label label = labels[((XirLabel) inst.extra).index];
+                        masm.jmp(label);
+                    } else {
+                        directJmp(inst.extra);
+                    }
+                    break;
+                }
+                case DecAndJumpNotZero: {
+                    Label label = labels[((XirLabel) inst.extra).index];
+                    CiValue value = operands[inst.x().index];
+                    if (value.kind == CiKind.Long) {
+                        masm.decq(value.asRegister());
+                    } else {
+                        assert value.kind == CiKind.Int;
+                        masm.decl(value.asRegister());
+                    }
+                    masm.jcc(ConditionFlag.notZero, label);
+                    break;
+                }
+                case Jeq: {
+                    Label label = labels[((XirLabel) inst.extra).index];
+                    emitXirCompare(inst, Condition.EQ, ConditionFlag.equal, operands, label);
+                    break;
+                }
+                case Jneq: {
+                    Label label = labels[((XirLabel) inst.extra).index];
+                    emitXirCompare(inst, Condition.NE, ConditionFlag.notEqual, operands, label);
+                    break;
+                }
+
+                case Jgt: {
+                    Label label = labels[((XirLabel) inst.extra).index];
+                    emitXirCompare(inst, Condition.GT, ConditionFlag.greater, operands, label);
+                    break;
+                }
+
+                case Jgteq: {
+                    Label label = labels[((XirLabel) inst.extra).index];
+                    emitXirCompare(inst, Condition.GE, ConditionFlag.greaterEqual, operands, label);
+                    break;
+                }
+
+                case Jugteq: {
+                    Label label = labels[((XirLabel) inst.extra).index];
+                    emitXirCompare(inst, Condition.AE, ConditionFlag.aboveEqual, operands, label);
+                    break;
+                }
+
+                case Jlt: {
+                    Label label = labels[((XirLabel) inst.extra).index];
+                    emitXirCompare(inst, Condition.LT, ConditionFlag.less, operands, label);
+                    break;
+                }
+
+                case Jlteq: {
+                    Label label = labels[((XirLabel) inst.extra).index];
+                    emitXirCompare(inst, Condition.LE, ConditionFlag.lessEqual, operands, label);
+                    break;
+                }
+
+                case Jbset: {
+                    Label label = labels[((XirLabel) inst.extra).index];
+                    CiValue pointer = operands[inst.x().index];
+                    CiValue offset = operands[inst.y().index];
+                    CiValue bit = operands[inst.z().index];
+                    assert offset.isConstant() && bit.isConstant();
+                    CiConstant constantOffset = (CiConstant) offset;
+                    CiConstant constantBit = (CiConstant) bit;
+                    CiAddress src = new CiAddress(inst.kind, pointer, constantOffset.asInt());
+                    masm.btli(src, constantBit.asInt());
+                    masm.jcc(ConditionFlag.aboveEqual, label);
+                    break;
+                }
+
+                case Bind: {
+                    XirLabel l = (XirLabel) inst.extra;
+                    Label label = labels[l.index];
+                    asm.bind(label);
+                    break;
+                }
+                case Safepoint: {
+                    assert info != null : "Must have debug info in order to create a safepoint.";
+                    tasm.recordSafepoint(codePos(), info);
+                    break;
+                }
+                case NullCheck: {
+                    tasm.recordImplicitException(codePos(), info);
+                    CiValue pointer = operands[inst.x().index];
+                    masm.nullCheck(pointer.asRegister());
+                    break;
+                }
+                case Align: {
+                    masm.align((Integer) inst.extra);
+                    break;
+                }
+                case StackOverflowCheck: {
+                    int frameSize = initialFrameSizeInBytes();
+                    int lastFramePage = frameSize / target.pageSize;
+                    // emit multiple stack bangs for methods with frames larger than a page
+                    for (int i = 0; i <= lastFramePage; i++) {
+                        int offset = (i + GraalOptions.StackShadowPages) * target.pageSize;
+                        // Deduct 'frameSize' to handle frames larger than the shadow
+                        bangStackWithOffset(offset - frameSize);
+                    }
+                    break;
+                }
+                case PushFrame: {
+                    int frameSize = initialFrameSizeInBytes();
+                    masm.decrementq(AMD64.rsp, frameSize); // does not emit code for frameSize == 0
+                    if (GraalOptions.ZapStackOnMethodEntry) {
+                        final int intSize = 4;
+                        for (int i = 0; i < frameSize / intSize; ++i) {
+                            masm.movl(new CiAddress(CiKind.Int, AMD64.rsp.asValue(), i * intSize), 0xC1C1C1C1);
+                        }
+                    }
+                    CiCalleeSaveLayout csa = compilation.registerConfig.getCalleeSaveLayout();
+                    if (csa.size != 0) {
+                        int frameToCSA = frameMap.offsetToCalleeSaveAreaStart();
+                        assert frameToCSA >= 0;
+                        masm.save(csa, frameToCSA);
+                    }
+                    break;
+                }
+                case PopFrame: {
+                    int frameSize = initialFrameSizeInBytes();
+
+                    CiCalleeSaveLayout csa = compilation.registerConfig.getCalleeSaveLayout();
+                    if (csa.size != 0) {
+                        registerRestoreEpilogueOffset = masm.codeBuffer.position();
+                        // saved all registers, restore all registers
+                        int frameToCSA = frameMap.offsetToCalleeSaveAreaStart();
+                        masm.restore(csa, frameToCSA);
+                    }
+
+                    masm.incrementq(AMD64.rsp, frameSize);
+                    break;
+                }
+                case Push: {
+                    CiRegisterValue value = assureInRegister(operands[inst.x().index]);
+                    masm.push(value.asRegister());
+                    break;
+                }
+                case Pop: {
+                    CiValue result = operands[inst.result.index];
+                    if (result.isRegister()) {
+                        masm.pop(result.asRegister());
+                    } else {
+                        masm.pop(rscratch1);
+                        moveOp(rscratch1.asValue(), result, result.kind, null, true);
+                    }
+                    break;
+                }
+                case Mark: {
+                    XirMark xmark = (XirMark) inst.extra;
+                    Mark[] references = new Mark[xmark.references.length];
+                    for (int i = 0; i < references.length; i++) {
+                        references[i] = marks.get(xmark.references[i]);
+                        assert references[i] != null;
+                    }
+                    Mark mark = tasm.recordMark(xmark.id, references);
+                    marks.put(xmark, mark);
+                    break;
+                }
+                case Nop: {
+                    for (int i = 0; i < (Integer) inst.extra; i++) {
+                        masm.nop();
+                    }
+                    break;
+                }
+                case RawBytes: {
+                    for (byte b : (byte[]) inst.extra) {
+                        masm.codeBuffer.emitByte(b & 0xff);
+                    }
+                    break;
+                }
+                case ShouldNotReachHere: {
+                    if (inst.extra == null) {
+                        stop("should not reach here");
+                    } else {
+                        stop("should not reach here: " + inst.extra);
+                    }
+                    break;
+                }
+                default:
+                    assert false : "Unknown XIR operation " + inst.op;
+            }
+        }
+    }
+
+    /**
+     * @param offset the offset RSP at which to bang. Note that this offset is relative to RSP after RSP has been
+     *            adjusted to allocated the frame for the method. It denotes an offset "down" the stack.
+     *            For very large frames, this means that the offset may actually be negative (i.e. denoting
+     *            a slot "up" the stack above RSP).
+     */
+    private void bangStackWithOffset(int offset) {
+        masm.movq(new CiAddress(CiKind.Word, AMD64.RSP, -offset), AMD64.rax);
+    }
+
+    private CiRegisterValue assureInRegister(CiValue pointer) {
+        if (pointer.isConstant()) {
+            CiRegisterValue register = rscratch1.asValue(pointer.kind);
+            moveOp(pointer, register, pointer.kind, null, false);
+            return register;
+        }
+
+        assert pointer.isRegister() : "should be register, but is: " + pointer;
+        return (CiRegisterValue) pointer;
+    }
+
+    private void emitXirCompare(XirInstruction inst, Condition condition, ConditionFlag cflag, CiValue[] ops, Label label) {
+        CiValue x = ops[inst.x().index];
+        CiValue y = ops[inst.y().index];
+        emitCompare(condition, x, y, null);
+        masm.jcc(cflag, label);
+    }
+
+    @Override
+    public void emitDeoptizationStub(DeoptimizationStub stub) {
+        masm.bind(stub.label);
+        int code;
+        switch(stub.action) {
+            case None:
+                code = 0;
+                break;
+            case Recompile:
+                code = 1;
+                break;
+            case InvalidateReprofile:
+                code = 2;
+                break;
+            case InvalidateRecompile:
+                code = 3;
+                break;
+            case InvalidateStopCompiling:
+                code = 4;
+                break;
+            default:
+                throw Util.shouldNotReachHere();
+        }
+        if (code == 0) {
+            throw new RuntimeException();
+        }
+        masm.movq(rscratch1, code);
+        directCall(CiRuntimeCall.Deoptimize, stub.info);
+        shouldNotReachHere();
+    }
+
+    public GlobalStub lookupGlobalStub(XirTemplate template) {
+        return compilation.compiler.lookupGlobalStub(template);
+    }
+
+    public void callGlobalStub(XirTemplate stub, LIRDebugInfo info, CiRegister result, CiValue... args) {
+        callGlobalStubHelper(lookupGlobalStub(stub), stub.resultOperand.kind, info, result, args);
+    }
+
+    public void callGlobalStub(GlobalStub stub, LIRDebugInfo info, CiRegister result, CiValue... args) {
+        callGlobalStubHelper(stub, stub.resultKind, info, result, args);
+    }
+
+    private void callGlobalStubHelper(GlobalStub stub, CiKind resultKind, LIRDebugInfo info, CiRegister result, CiValue... args) {
+        assert args.length == stub.argOffsets.length;
+
+        for (int i = 0; i < args.length; i++) {
+            storeParameter(args[i], stub.argOffsets[i]);
+        }
+
+        directCall(stub.stubObject, info);
+
+        if (result != CiRegister.None) {
+            loadResult(result, stub.resultOffset, resultKind);
+        }
+
+        // Clear out parameters
+        if (GraalOptions.GenAssertionCode) {
+            for (int i = 0; i < args.length; i++) {
+                masm.movptr(new CiAddress(CiKind.Word, AMD64.RSP, stub.argOffsets[i]), 0);
+            }
+        }
+    }
+
+    private void loadResult(CiRegister r, int offset, CiKind kind) {
+        if (kind == CiKind.Int || kind == CiKind.Boolean) {
+            masm.movl(r, new CiAddress(CiKind.Int, AMD64.RSP, offset));
+        } else if (kind == CiKind.Float) {
+            masm.movss(r, new CiAddress(CiKind.Float, AMD64.RSP, offset));
+        } else if (kind == CiKind.Double) {
+            masm.movsd(r, new CiAddress(CiKind.Double, AMD64.RSP, offset));
+        } else {
+            masm.movq(r, new CiAddress(CiKind.Word, AMD64.RSP, offset));
+        }
+    }
+
+    private void storeParameter(CiValue registerOrConstant, int offset) {
+        CiKind k = registerOrConstant.kind;
+        if (registerOrConstant.isConstant()) {
+            CiConstant c = (CiConstant) registerOrConstant;
+            if (c.kind == CiKind.Object) {
+                movoop(new CiAddress(CiKind.Word, AMD64.RSP, offset), c);
+            } else {
+                masm.movptr(new CiAddress(CiKind.Word, AMD64.RSP, offset), c.asInt());
+            }
+        } else if (registerOrConstant.isRegister()) {
+            if (k.isFloat()) {
+                masm.movss(new CiAddress(CiKind.Float, AMD64.RSP, offset), registerOrConstant.asRegister());
+            } else if (k.isDouble()) {
+                masm.movsd(new CiAddress(CiKind.Double, AMD64.RSP, offset), registerOrConstant.asRegister());
+            } else {
+                masm.movq(new CiAddress(CiKind.Word, AMD64.RSP, offset), registerOrConstant.asRegister());
+            }
+        } else {
+            throw new InternalError("should not reach here");
+        }
+    }
+
+    public void movoop(CiRegister dst, CiConstant obj) {
+        assert obj.kind == CiKind.Object;
+        if (obj.isNull()) {
+            masm.xorq(dst, dst);
+        } else {
+            if (target.inlineObjects) {
+                tasm.recordDataReferenceInCode(obj);
+                masm.movq(dst, 0xDEADDEADDEADDEADL);
+            } else {
+                masm.movq(dst, tasm.recordDataReferenceInCode(obj));
+            }
+        }
+    }
+
+    public void movoop(CiAddress dst, CiConstant obj) {
+        movoop(rscratch1, obj);
+        masm.movq(dst, rscratch1);
+    }
+
+    public void directCall(Object target, LIRDebugInfo info) {
+        int before = masm.codeBuffer.position();
+        masm.call();
+        int after = masm.codeBuffer.position();
+        tasm.recordDirectCall(before, after, target, info);
+        tasm.recordExceptionHandlers(after, info);
+    }
+
+    public void directJmp(Object target) {
+        int before = masm.codeBuffer.position();
+        masm.jmp(0, true);
+        int after = masm.codeBuffer.position();
+        tasm.recordDirectCall(before, after, target, null);
+    }
+
+    public void indirectCall(CiRegister dst, Object target, LIRDebugInfo info) {
+        int before = masm.codeBuffer.position();
+        masm.call(dst);
+        int after = masm.codeBuffer.position();
+        tasm.recordIndirectCall(before, after, target, info);
+        tasm.recordExceptionHandlers(after, info);
+    }
+
+    protected void stop(String msg) {
+        if (GraalOptions.GenAssertionCode) {
+            // TODO: pass a pointer to the message
+            directCall(CiRuntimeCall.Debug, null);
+            masm.hlt();
+        }
+    }
+
+    public void shouldNotReachHere() {
+        stop("should not reach here");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,472 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.max.graal.compiler.target.amd64;
+
+import com.oracle.max.asm.*;
+import com.oracle.max.asm.target.amd64.*;
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.compiler.globalstub.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.lir.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+/**
+ * This class implements the X86-specific portion of the LIR generator.
+ */
+public class AMD64LIRGenerator extends LIRGenerator {
+
+    private static final CiRegisterValue RAX_I = AMD64.rax.asValue(CiKind.Int);
+    private static final CiRegisterValue RAX_L = AMD64.rax.asValue(CiKind.Long);
+    private static final CiRegisterValue RAX_W = AMD64.rax.asValue(CiKind.Word);
+    private static final CiRegisterValue RDX_I = AMD64.rdx.asValue(CiKind.Int);
+    private static final CiRegisterValue RDX_L = AMD64.rdx.asValue(CiKind.Long);
+
+    private static final CiRegisterValue LDIV_TMP = RDX_L;
+
+
+    /**
+     * The register in which MUL puts the result for 64-bit multiplication.
+     */
+    private static final CiRegisterValue LMUL_OUT = RAX_L;
+
+    private static final CiRegisterValue SHIFT_COUNT_IN = AMD64.rcx.asValue(CiKind.Int);
+
+    protected static final CiValue ILLEGAL = CiValue.IllegalValue;
+
+    public AMD64LIRGenerator(GraalCompilation compilation) {
+        super(compilation);
+    }
+
+    @Override
+    protected boolean canStoreAsConstant(Value v, CiKind kind) {
+        if (kind == CiKind.Short || kind == CiKind.Char) {
+            // there is no immediate move of word values in asemblerI486.?pp
+            return false;
+        }
+        return v instanceof Constant;
+    }
+
+    @Override
+    protected boolean canInlineAsConstant(Value v) {
+        if (v.kind == CiKind.Long) {
+            if (v.isConstant() && NumUtil.isInt(v.asConstant().asLong())) {
+                return true;
+            }
+            return false;
+        }
+        return v.kind != CiKind.Object || v.isNullConstant();
+    }
+
+    @Override
+    protected CiAddress genAddress(CiValue base, CiValue index, int shift, int disp, CiKind kind) {
+        assert base.isVariableOrRegister();
+        if (index.isConstant()) {
+            return new CiAddress(kind, base, (((CiConstant) index).asInt() << shift) + disp);
+        } else {
+            assert index.isVariableOrRegister();
+            return new CiAddress(kind, base, (index), CiAddress.Scale.fromShift(shift), disp);
+        }
+    }
+
+    @Override
+    protected void genCmpMemInt(Condition condition, CiValue base, int disp, int c, LIRDebugInfo info) {
+        lir.cmpMemInt(condition, base, disp, c, info);
+    }
+
+    @Override
+    protected void genCmpRegMem(Condition condition, CiValue reg, CiValue base, int disp, CiKind kind, LIRDebugInfo info) {
+        lir.cmpRegMem(condition, reg, new CiAddress(kind, base, disp), info);
+    }
+
+    @Override
+    protected boolean strengthReduceMultiply(CiValue left, int c, CiValue result, CiValue tmp) {
+        if (tmp.isLegal()) {
+            if (CiUtil.isPowerOf2(c + 1)) {
+                lir.move(left, tmp);
+                lir.shiftLeft(left, CiUtil.log2(c + 1), left);
+                lir.sub(left, tmp, result);
+                return true;
+            } else if (CiUtil.isPowerOf2(c - 1)) {
+                lir.move(left, tmp);
+                lir.shiftLeft(left, CiUtil.log2(c - 1), left);
+                lir.add(left, tmp, result);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public void visitNegate(Negate x) {
+        LIRItem value = new LIRItem(x.x(), this);
+        value.setDestroysRegister();
+        value.loadItem();
+        CiVariable reg = newVariable(x.kind);
+        GlobalStub globalStub = null;
+        if (x.kind == CiKind.Float) {
+            globalStub = stubFor(GlobalStub.Id.fneg);
+        } else if (x.kind == CiKind.Double) {
+            globalStub = stubFor(GlobalStub.Id.dneg);
+        }
+        lir.negate(value.result(), reg, globalStub);
+        setResult(x, reg);
+    }
+
+    public boolean livesLonger(Value x, Value y) {
+        // TODO(tw): Estimate which value will live longer.
+        return false;
+    }
+
+    public void visitArithmeticOpFloat(Arithmetic x) {
+        LIRItem left = new LIRItem(x.x(), this);
+        LIRItem right = new LIRItem(x.y(), this);
+        assert !left.isStack() || !right.isStack() : "can't both be memory operands";
+        boolean mustLoadBoth = x.opcode == Bytecodes.FREM || x.opcode == Bytecodes.DREM;
+
+        // Both are in register, swap operands such that the short-living one is on the left side.
+        if (x.isCommutative() && left.isRegisterOrVariable() && right.isRegisterOrVariable()) {
+            if (livesLonger(x.x(), x.y())) {
+                LIRItem tmp = left;
+                left = right;
+                right = tmp;
+            }
+        }
+
+        if (left.isRegisterOrVariable() || x.x().isConstant() || mustLoadBoth) {
+            left.loadItem();
+        }
+
+        if (mustLoadBoth) {
+            // frem and drem destroy also right operand, so move it to a new register
+            right.setDestroysRegister();
+            right.loadItem();
+        } else if (right.isRegisterOrVariable()) {
+            right.loadItem();
+        }
+
+        CiVariable reg;
+
+        if (x.opcode == Bytecodes.FREM) {
+            reg = callRuntimeWithResult(CiRuntimeCall.ArithmeticFrem, null, left.result(), right.result());
+        } else if (x.opcode == Bytecodes.DREM) {
+            reg = callRuntimeWithResult(CiRuntimeCall.ArithmeticDrem, null, left.result(), right.result());
+        } else {
+            reg = newVariable(x.kind);
+            arithmeticOpFpu(x.opcode, reg, left.result(), right.result(), ILLEGAL);
+        }
+
+        setResult(x, reg);
+    }
+
+    public void visitArithmeticOpLong(Arithmetic x) {
+        int opcode = x.opcode;
+        if (opcode == Bytecodes.LDIV || opcode == Bytecodes.LREM) {
+            // emit inline 64-bit code
+            LIRDebugInfo info = stateFor(x);
+            CiValue dividend = force(x.x(), RAX_L); // dividend must be in RAX
+            CiValue divisor = load(x.y());            // divisor can be in any (other) register
+
+            CiValue result = createResultVariable(x);
+            CiValue resultReg;
+            if (opcode == Bytecodes.LREM) {
+                resultReg = RDX_L; // remainder result is produced in rdx
+                lir.lrem(dividend, divisor, resultReg, LDIV_TMP, info);
+            } else {
+                resultReg = RAX_L; // division result is produced in rax
+                lir.ldiv(dividend, divisor, resultReg, LDIV_TMP, info);
+            }
+
+            lir.move(resultReg, result);
+        } else if (opcode == Bytecodes.LMUL) {
+            LIRItem right = new LIRItem(x.y(), this);
+
+            // right register is destroyed by the long mul, so it must be
+            // copied to a new register.
+            right.setDestroysRegister();
+
+            CiValue left = load(x.x());
+            right.loadItem();
+
+            arithmeticOpLong(opcode, LMUL_OUT, left, right.result());
+            CiValue result = createResultVariable(x);
+            lir.move(LMUL_OUT, result);
+        } else {
+            LIRItem right = new LIRItem(x.y(), this);
+
+            CiValue left = load(x.x());
+            // don't load constants to save register
+            right.loadNonconstant();
+            createResultVariable(x);
+            arithmeticOpLong(opcode, x.operand(), left, right.result());
+        }
+    }
+
+    public void visitArithmeticOpInt(Arithmetic x) {
+        int opcode = x.opcode;
+        if (opcode == Bytecodes.IDIV || opcode == Bytecodes.IREM) {
+            // emit code for integer division or modulus
+
+            // Call 'stateFor' before 'force()' because 'stateFor()' may
+            // force the evaluation of other instructions that are needed for
+            // correct debug info.  Otherwise the live range of the fixed
+            // register might be too long.
+            LIRDebugInfo info = stateFor(x);
+
+            CiValue dividend = force(x.x(), RAX_I); // dividend must be in RAX
+            CiValue divisor = load(x.y());          // divisor can be in any (other) register
+
+            // idiv and irem use rdx in their implementation so the
+            // register allocator must not assign it to an interval that overlaps
+            // this division instruction.
+            CiRegisterValue tmp = RDX_I;
+
+            CiValue result = createResultVariable(x);
+            CiValue resultReg;
+            if (opcode == Bytecodes.IREM) {
+                resultReg = tmp; // remainder result is produced in rdx
+                lir.irem(dividend, divisor, resultReg, tmp, info);
+            } else {
+                resultReg = RAX_I; // division result is produced in rax
+                lir.idiv(dividend, divisor, resultReg, tmp, info);
+            }
+
+            lir.move(resultReg, result);
+        } else {
+            // emit code for other integer operations
+            LIRItem left = new LIRItem(x.x(), this);
+            LIRItem right = new LIRItem(x.y(), this);
+            LIRItem leftArg = left;
+            LIRItem rightArg = right;
+            if (x.isCommutative() && left.isStack() && right.isRegisterOrVariable()) {
+                // swap them if left is real stack (or cached) and right is real register(not cached)
+                leftArg = right;
+                rightArg = left;
+            }
+
+            leftArg.loadItem();
+
+            // do not need to load right, as we can handle stack and constants
+            if (opcode == Bytecodes.IMUL) {
+                // check if we can use shift instead
+                boolean useConstant = false;
+                boolean useTmp = false;
+                if (rightArg.result().isConstant()) {
+                    int iconst = rightArg.instruction.asConstant().asInt();
+                    if (iconst > 0) {
+                        if (CiUtil.isPowerOf2(iconst)) {
+                            useConstant = true;
+                        } else if (CiUtil.isPowerOf2(iconst - 1) || CiUtil.isPowerOf2(iconst + 1)) {
+                            useConstant = true;
+                            useTmp = true;
+                        }
+                    }
+                }
+                if (!useConstant) {
+                    rightArg.loadItem();
+                }
+                CiValue tmp = ILLEGAL;
+                if (useTmp) {
+                    tmp = newVariable(CiKind.Int);
+                }
+                createResultVariable(x);
+
+                arithmeticOpInt(opcode, x.operand(), leftArg.result(), rightArg.result(), tmp);
+            } else {
+                createResultVariable(x);
+                CiValue tmp = ILLEGAL;
+                arithmeticOpInt(opcode, x.operand(), leftArg.result(), rightArg.result(), tmp);
+            }
+        }
+    }
+
+    public void visitArithmeticOpWord(Arithmetic x) {
+        int opcode = x.opcode;
+        if (opcode == Bytecodes.WDIV || opcode == Bytecodes.WREM || opcode == Bytecodes.WDIVI || opcode == Bytecodes.WREMI) {
+            // emit code for long division or modulus
+                // emit inline 64-bit code
+                LIRDebugInfo info = stateFor(x);
+                CiValue dividend = force(x.x(), RAX_L); // dividend must be in RAX
+                CiValue divisor = load(x.y());            // divisor can be in any (other) register
+
+                CiValue result = createResultVariable(x);
+                CiValue resultReg;
+                if (opcode == Bytecodes.WREM) {
+                    resultReg = RDX_L; // remainder result is produced in rdx
+                    lir.wrem(dividend, divisor, resultReg, LDIV_TMP, info);
+                } else if (opcode == Bytecodes.WREMI) {
+                    resultReg = RDX_L; // remainder result is produced in rdx
+                    lir.wremi(dividend, divisor, resultReg, LDIV_TMP, info);
+                } else if (opcode == Bytecodes.WDIV) {
+                    resultReg = RAX_L; // division result is produced in rax
+                    lir.wdiv(dividend, divisor, resultReg, LDIV_TMP, info);
+                } else {
+                    assert opcode == Bytecodes.WDIVI;
+                    resultReg = RAX_L; // division result is produced in rax
+                    lir.wdivi(dividend, divisor, resultReg, LDIV_TMP, info);
+                }
+
+                lir.move(resultReg, result);
+        } else if (opcode == Bytecodes.LMUL) {
+            LIRItem right = new LIRItem(x.y(), this);
+
+            // right register is destroyed by the long mul, so it must be
+            // copied to a new register.
+            right.setDestroysRegister();
+
+            CiValue left = load(x.x());
+            right.loadItem();
+
+            CiValue reg = LMUL_OUT;
+            arithmeticOpLong(opcode, reg, left, right.result());
+            CiValue result = createResultVariable(x);
+            lir.move(reg, result);
+        } else {
+            LIRItem right = new LIRItem(x.y(), this);
+
+            CiValue left = load(x.x());
+            // don't load constants to save register
+            right.loadNonconstant();
+            createResultVariable(x);
+            arithmeticOpLong(opcode, x.operand(), left, right.result());
+        }
+    }
+
+    @Override
+    public void visitArithmetic(Arithmetic x) {
+        trySwap(x);
+
+        if (x.kind.isWord() || x.opcode == Bytecodes.WREMI) {
+            visitArithmeticOpWord(x);
+            return;
+        }
+
+        assert Util.archKindsEqual(x.x().kind, x.kind) && Util.archKindsEqual(x.y().kind, x.kind) : "wrong parameter types: " + Bytecodes.nameOf(x.opcode) + ", x: " + x.x() + ", y: " + x.y() + ", kind: " + x.kind;
+        switch (x.kind) {
+            case Float:
+            case Double:
+                visitArithmeticOpFloat(x);
+                return;
+            case Long:
+                visitArithmeticOpLong(x);
+                return;
+            case Int:
+                visitArithmeticOpInt(x);
+                return;
+        }
+        throw Util.shouldNotReachHere();
+    }
+
+    @Override
+    public void visitShift(Shift x) {
+        // count must always be in rcx
+        CiValue count = makeOperand(x.y());
+        boolean mustLoadCount = !count.isConstant() || x.kind == CiKind.Long;
+        if (mustLoadCount) {
+            // count for long must be in register
+            count = force(x.y(), SHIFT_COUNT_IN);
+        }
+
+        CiValue value = load(x.x());
+        CiValue reg = createResultVariable(x);
+
+        shiftOp(x.opcode, reg, value, count, ILLEGAL);
+    }
+
+    @Override
+    public void visitLogic(Logic x) {
+        trySwap(x);
+
+        LIRItem right = new LIRItem(x.y(), this);
+
+        CiValue left = load(x.x());
+        right.loadNonconstant();
+        CiValue reg = createResultVariable(x);
+
+        logicOp(x.opcode, reg, left, right.result());
+    }
+
+    private void trySwap(Binary x) {
+        // (tw) TODO: Check what this is for?
+    }
+
+    @Override
+    public void visitMaterialize(NormalizeCompare x) {
+        LIRItem left = new LIRItem(x.x(), this);
+        LIRItem right = new LIRItem(x.y(), this);
+        if (!x.kind.isVoid() && x.x().kind.isLong()) {
+            left.setDestroysRegister();
+        }
+        left.loadItem();
+        right.loadItem();
+
+        if (x.kind.isVoid()) {
+            lir.cmp(Condition.TRUE, left.result(), right.result());
+        } else if (x.x().kind.isFloat() || x.x().kind.isDouble()) {
+            CiValue reg = createResultVariable(x);
+            lir.fcmp2int(left.result(), right.result(), reg, x.isUnorderedLess());
+        } else if (x.x().kind.isLong() || x.x().kind.isWord()) {
+            CiValue reg = createResultVariable(x);
+            lir.lcmp2int(left.result(), right.result(), reg);
+        } else {
+            assert false;
+        }
+    }
+
+    @Override
+    public void visitConvert(Convert x) {
+        CiValue input = load(x.value());
+        CiVariable result = newVariable(x.kind);
+        // arguments of lirConvert
+        GlobalStub globalStub = null;
+        // Checkstyle: off
+        switch (x.opcode) {
+            case Bytecodes.F2I: globalStub = stubFor(GlobalStub.Id.f2i); break;
+            case Bytecodes.F2L: globalStub = stubFor(GlobalStub.Id.f2l); break;
+            case Bytecodes.D2I: globalStub = stubFor(GlobalStub.Id.d2i); break;
+            case Bytecodes.D2L: globalStub = stubFor(GlobalStub.Id.d2l); break;
+        }
+        // Checkstyle: on
+        if (globalStub != null) {
+            // Force result to be rax to match global stubs expectation.
+            CiValue stubResult = x.kind == CiKind.Int ? RAX_I : RAX_L;
+            lir.convert(x.opcode, input, stubResult, globalStub);
+            lir.move(stubResult, result);
+        } else {
+            lir.convert(x.opcode, input, result, globalStub);
+        }
+        setResult(x, result);
+    }
+
+    @Override
+    public void visitLoopBegin(LoopBegin x) {
+    }
+
+    @Override
+    public void visitValueAnchor(ValueAnchor valueAnchor) {
+        // nothing to do for ValueAnchors
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64XirAssembler.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.target.amd64;
+
+import static com.sun.cri.xir.XirTemplate.GlobalFlags.*;
+
+import java.util.*;
+
+import com.oracle.max.asm.target.amd64.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.xir.*;
+
+/**
+ * AMD64 version of {@link CiXirAssembler}.
+ *
+ * @author Thomas Wuerthinger
+ *
+ */
+public class AMD64XirAssembler extends CiXirAssembler {
+
+    @Override
+    protected XirTemplate buildTemplate(String name, boolean isStub) {
+        List<XirInstruction> fastPath = new ArrayList<XirInstruction>(instructions.size());
+        List<XirInstruction> slowPath = new ArrayList<XirInstruction>();
+        List<XirTemplate> calleeTemplates = new ArrayList<XirTemplate>();
+
+        int flags = 0;
+
+        if (isStub) {
+            flags |= GLOBAL_STUB.mask;
+        }
+
+        List<XirInstruction> currentList = fastPath;
+
+        XirOperand fixedRDX = null;
+        XirOperand fixedRAX = null;
+        XirOperand fixedRCX = null;
+        XirOperand fixedRSI = null;
+        XirOperand fixedRDI = null;
+        HashSet<XirLabel> boundLabels = new HashSet<XirLabel>();
+
+        for (XirInstruction i : instructions) {
+            boolean appended = false;
+            switch (i.op) {
+                case Mov:
+                    break;
+
+                case Add:
+                case Sub:
+                case Div:
+                case Mul:
+                case Mod:
+                case Shl:
+                case Shr:
+                case And:
+                case Or:
+                case Xor:
+                    // Convert to two operand form
+                    XirOperand xOp = i.x();
+                    if (i.op == XirOp.Div || i.op == XirOp.Mod) {
+                        if (fixedRDX == null) {
+                            fixedRDX = createRegisterTemp("divModTemp", CiKind.Int, AMD64.rdx);
+                        }
+                        // Special treatment to make sure that the left input of % and / is in RAX
+                        if (fixedRAX == null) {
+                            fixedRAX = createRegisterTemp("divModLeftInput", CiKind.Int, AMD64.rax);
+                        }
+                        currentList.add(new XirInstruction(i.x().kind, XirOp.Mov, fixedRAX, i.x()));
+                        xOp = fixedRAX;
+                    } else {
+                        if (i.result != i.x()) {
+                            currentList.add(new XirInstruction(i.result.kind, XirOp.Mov, i.result, i.x()));
+                            xOp = i.result;
+                        }
+                    }
+
+                    XirOperand yOp = i.y();
+                    if ((i.op == XirOp.Shl || i.op == XirOp.Shr) && (!(i.y() instanceof XirConstantOperand))) {
+                        // Special treatment to make sure that the shift count is always in RCX
+                        if (fixedRCX == null) {
+                            fixedRCX = createRegisterTemp("fixedShiftCount", i.y().kind, AMD64.rcx);
+                        }
+                        currentList.add(new XirInstruction(i.result.kind, XirOp.Mov, fixedRCX, i.y()));
+                        yOp = fixedRCX;
+                    } else if (i.op == XirOp.Mul && (i.y() instanceof XirConstantOperand)) {
+                        // Cannot multiply directly with a constant, so introduce a new temporary variable
+                        XirOperand tempLocation = createTemp("mulTempLocation", i.y().kind);
+                        currentList.add(new XirInstruction(i.result.kind, XirOp.Mov, tempLocation, i.y()));
+                        yOp = tempLocation;
+
+                    }
+
+                    if (xOp != i.x() || yOp != i.y()) {
+                        currentList.add(new XirInstruction(i.result.kind, i.op, i.result, xOp, yOp));
+                        appended = true;
+                    }
+                    break;
+
+                case RepeatMoveWords:
+                case RepeatMoveBytes:
+                    if (fixedRSI == null) {
+                        fixedRSI = createRegisterTemp("fixedRSI", CiKind.Word, AMD64.rsi);
+                    }
+                    if (fixedRDI == null) {
+                        fixedRDI = createRegisterTemp("fixedRDI", CiKind.Word, AMD64.rdi);
+                    }
+                    if (fixedRCX == null) {
+                        fixedRCX = createRegisterTemp("fixedRCX", CiKind.Word, AMD64.rcx);
+                    }
+                    currentList.add(new XirInstruction(CiKind.Word, XirOp.Mov, fixedRSI, i.x()));
+                    currentList.add(new XirInstruction(CiKind.Word, XirOp.Mov, fixedRDI, i.y()));
+                    currentList.add(new XirInstruction(CiKind.Word, XirOp.Mov, fixedRCX, i.z()));
+                    currentList.add(new XirInstruction(CiKind.Illegal, i.op, i.result, fixedRSI, fixedRDI, fixedRCX));
+                    appended = true;
+                    break;
+
+                case NullCheck:
+                case PointerLoad:
+                case LoadEffectiveAddress:
+                case PointerStore:
+                case PointerLoadDisp:
+                case PointerStoreDisp:
+                    break;
+                case PointerCAS:
+                    if (fixedRAX == null) {
+                        fixedRAX = createRegisterTemp("fixedRAX", CiKind.Word, AMD64.rax);
+                    }
+                    // x = source of cmpxch
+                    // y = new value
+                    // z = old value (i.e., the one compared to). Must be in RAX (and so must the result).
+                    currentList.add(new XirInstruction(CiKind.Word, XirOp.Mov, fixedRAX, i.z()));
+                    currentList.add(new XirInstruction(i.kind, i.op, i.result, i.x(), i.y(), fixedRAX));
+                    appended = true;
+                    break;
+                case CallStub:
+                    flags |= HAS_STUB_CALL.mask;
+                    calleeTemplates.add((XirTemplate) i.extra);
+                    break;
+                case CallRuntime:
+                    flags |= HAS_RUNTIME_CALL.mask;
+                    break;
+                case Jmp:
+                    // jmp can be either into the snippet or to a runtime target
+                    flags |= i.extra instanceof XirLabel ? HAS_CONTROL_FLOW.mask : HAS_RUNTIME_CALL.mask;
+                    break;
+                case Jeq:
+                case Jneq:
+                case Jgt:
+                case Jgteq:
+                case Jugteq:
+                case Jlt:
+                case Jlteq:
+                case DecAndJumpNotZero:
+                case Jbset:
+                    flags |= HAS_CONTROL_FLOW.mask;
+                    break;
+                case Bind:
+                    XirLabel label = (XirLabel) i.extra;
+                    currentList = label.inline ? fastPath : slowPath;
+                    assert !boundLabels.contains(label) : "label may be bound only once";
+                    boundLabels.add(label);
+                    break;
+                case Safepoint:
+                case Align:
+                case StackOverflowCheck:
+                case PushFrame:
+                case PopFrame:
+                case Push:
+                case Pop:
+                case Mark:
+                case Nop:
+                case RawBytes:
+                case ShouldNotReachHere:
+                    break;
+                default:
+                    assert false : "Unknown XIR operation " + i.op;
+            }
+            if (!appended) {
+                currentList.add(i);
+            }
+        }
+        for (XirLabel label : labels) {
+            assert label.name == XirLabel.TrueSuccessor || label.name == XirLabel.FalseSuccessor || boundLabels.contains(label) : "label " + label.name + " is not bound!";
+        }
+        XirInstruction[] fp = fastPath.toArray(new XirInstruction[fastPath.size()]);
+        XirInstruction[] sp = slowPath.size() > 0 ? slowPath.toArray(new XirInstruction[slowPath.size()]) : null;
+        XirLabel[] xirLabels = labels.toArray(new XirLabel[labels.size()]);
+        XirParameter[] xirParameters = parameters.toArray(new XirParameter[parameters.size()]);
+        XirTemp[] temporaryOperands = temps.toArray(new XirTemp[temps.size()]);
+        XirConstant[] constantOperands = constants.toArray(new XirConstant[constants.size()]);
+        XirTemplate[] calleeTemplateArray = calleeTemplates.toArray(new XirTemplate[calleeTemplates.size()]);
+        XirMark[] marksArray = marks.toArray(new XirMark[marks.size()]);
+        return new XirTemplate(name, this.variableCount, this.allocateResultOperand, resultOperand, fp, sp, xirLabels, xirParameters, temporaryOperands, constantOperands, flags, calleeTemplateArray, marksArray, outgoingStackSize);
+    }
+
+    @Override
+    public CiXirAssembler copy() {
+        return new AMD64XirAssembler();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/ArrayMap.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.util;
+
+/**
+ * The {@code ArrayMap} class implements an efficient one-level map which is implemented
+ * as an array. Note that because of the one-level array inside, this data structure performs best
+ * when the range of integer keys is small and densely used. Note that the implementation can
+ * handle arbitrary intervals, including negative numbers, up to intervals of size 2^31 - 1.
+ *
+ * @author Ben L. Titzer
+ */
+public class ArrayMap<T> {
+
+    private static final int INITIAL_SIZE = 5; // how big the initial array should be
+    private static final int EXTRA = 2; // how far on the left or right of a new element to grow
+
+    Object[] map;
+    int low;
+
+    /**
+     * Constructs a new {@code ArrayMap} with no initial assumptions.
+     */
+    public ArrayMap() {
+    }
+
+    /**
+     * Constructs a new {@code ArrayMap} that initially covers the specified interval.
+     * Note that this map will automatically expand if necessary later.
+     * @param low the low index, inclusive
+     * @param high the high index, exclusive
+     */
+    public ArrayMap(int low, int high) {
+        this.low = low;
+        this.map = new Object[high - low + 1];
+    }
+
+    /**
+     * Puts a new value in the map at the specified index.
+     * @param i the index at which to store the value
+     * @param value the value to store at the specified index
+     */
+    public void put(int i, T value) {
+        int index = i - low;
+        if (map == null) {
+            // no map yet
+            map = new Object[INITIAL_SIZE];
+            low = index - 2;
+            map[INITIAL_SIZE / 2] = value;
+        } else if (index < 0) {
+            // grow backwards
+            growBackward(i, value);
+        } else if (index >= map.length) {
+            // grow forwards
+            growForward(i, value);
+        } else {
+            // no growth necessary
+            map[index] = value;
+        }
+    }
+
+    /**
+     * Gets the value at the specified index in the map.
+     * @param i the index
+     * @return the value at the specified index; {@code null} if there is no value at the specified index,
+     * or if the index is out of the currently stored range
+     */
+    public T get(int i) {
+        int index = i - low;
+        if (map == null || index < 0 || index >= map.length) {
+            return null;
+        }
+        Class<T> type = null;
+        return Util.uncheckedCast(type, map[index]);
+    }
+
+    public int length() {
+        return map.length;
+    }
+
+    private void growBackward(int i, T value) {
+        int nlow = i - EXTRA;
+        Object[] nmap = new Object[low - nlow + map.length];
+        System.arraycopy(map, 0, nmap, low - nlow, map.length);
+        map = nmap;
+        low = nlow;
+        map[i - low] = value;
+    }
+
+    private void growForward(int i, T value) {
+        int nlen = i - low + 1 + EXTRA;
+        Object[] nmap = new Object[nlen];
+        System.arraycopy(map, 0, nmap, 0, map.length);
+        map = nmap;
+        map[i - low] = value;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/BitMap2D.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.util;
+
+import com.oracle.max.graal.graph.*;
+
+/**
+ * This class implements a two-dimensional bitmap.
+ *
+ * @author Marcelo Cintra
+ * @author Thomas Wuerthinger
+ */
+public final class BitMap2D {
+
+    private BitMap map;
+    private final int bitsPerSlot;
+
+    private int bitIndex(int slotIndex, int bitWithinSlotIndex)  {
+      return slotIndex * bitsPerSlot + bitWithinSlotIndex;
+    }
+
+    private boolean verifyBitWithinSlotIndex(int index)  {
+      assert index < bitsPerSlot : "index " + index + " is out of bounds " + bitsPerSlot;
+      return true;
+    }
+
+    public BitMap2D(int sizeInSlots, int bitsPerSlot) {
+        map = new BitMap(sizeInSlots * bitsPerSlot);
+        this.bitsPerSlot = bitsPerSlot;
+    }
+
+    public int sizeInBits() {
+      return map.size();
+    }
+
+    // Returns number of full slots that have been allocated
+    public int sizeInSlots() {
+      return map.size() / bitsPerSlot;
+    }
+
+    public boolean isValidIndex(int slotIndex, int bitWithinSlotIndex) {
+      assert verifyBitWithinSlotIndex(bitWithinSlotIndex);
+      return (bitIndex(slotIndex, bitWithinSlotIndex) < sizeInBits());
+    }
+
+    public boolean at(int slotIndex, int bitWithinSlotIndex)  {
+      assert verifyBitWithinSlotIndex(bitWithinSlotIndex);
+      return map.get(bitIndex(slotIndex, bitWithinSlotIndex));
+    }
+
+    public void setBit(int slotIndex, int bitWithinSlotIndex) {
+      assert verifyBitWithinSlotIndex(bitWithinSlotIndex);
+      map.set(bitIndex(slotIndex, bitWithinSlotIndex));
+    }
+
+    public void clearBit(int slotIndex, int bitWithinSlotIndex) {
+      assert verifyBitWithinSlotIndex(bitWithinSlotIndex);
+      map.clear(bitIndex(slotIndex, bitWithinSlotIndex));
+    }
+
+    public void atPutGrow(int slotIndex, int bitWithinSlotIndex, boolean value) {
+       int size = sizeInSlots();
+       if (size <= slotIndex) {
+           while (size <= slotIndex) {
+               size *= 2;
+           }
+           BitMap newBitMap = new BitMap(size * bitsPerSlot);
+           newBitMap.setUnion(map);
+           map = newBitMap;
+       }
+
+       if (value) {
+           setBit(slotIndex, bitWithinSlotIndex);
+       } else {
+           clearBit(slotIndex, bitWithinSlotIndex);
+       }
+    }
+
+    public void clear() {
+        map.clearAll();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/BlockWorkList.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2009, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.util;
+
+import com.oracle.max.graal.compiler.ir.*;
+
+/**
+ * This class implements a worklist for dealing with blocks. The worklist can
+ * operate either as a stack (i.e. first-in / last-out), or as a sorted list,
+ * where blocks can be sorted by a supplied number. The latter usage lends itself
+ * naturally to iterative dataflow analysis problems.
+ *
+ * This implementation is not able to tell if a block is in the worklist already.
+ * Note that this implementation is slightly less efficient than the dedicated
+ * work list in {@link com.oracle.max.graal.compiler.graph.ScopeData}, because this worklist uses
+ * an externally supplied number.
+ *
+ * @author Ben L. Titzer
+ */
+public class BlockWorkList {
+    Merge[] workList;
+    int[] workListNumbers;
+    int workListIndex;
+
+    /**
+     * Adds a block to this list in an unsorted fashion, like a stack.
+     * @param block the block to add
+     */
+    public void add(Merge block) {
+        if (workList == null) {
+            // worklist not allocated yet
+            allocate();
+        } else if (workListIndex == workList.length) {
+            // need to grow the worklist
+            grow();
+        }
+        // put the block at the end of the array
+        workList[workListIndex++] = block;
+    }
+
+    /**
+     * Adds a block to this list, sorted by the supplied number. The block
+     * with the lowest number is returned upon subsequent removes.
+     * @param block the block to add
+     * @param number the number used to sort the block
+     */
+    public void addSorted(Merge block, int number) {
+        if (workList == null) {
+            // worklist not allocated yet
+            allocate();
+        } else if (workListIndex == workList.length) {
+            // need to grow the worklist
+            grow();
+        }
+        // put the block at the end of the array
+        workList[workListIndex] = block;
+        workListNumbers[workListIndex] = number;
+        workListIndex++;
+        int i = workListIndex - 2;
+        // push block towards the beginning of the array
+        for (; i >= 0; i--) {
+            int n = workListNumbers[i];
+            if (n >= number) {
+                break; // already in the right position
+            }
+            workList[i + 1] = workList[i]; // bubble b down by one
+            workList[i] = block;           // and overwrite its place with block
+            workListNumbers[i + 1] = n;    // bubble n down by one
+            workListNumbers[i] = number;   // and overwrite its place with number
+        }
+    }
+
+    /**
+     * Removes the next block from this work list. If the blocks have been added
+     * in a sorted order, then the block with the lowest number is returned. Otherwise,
+     * the last block added is returned.
+     * @return the next block in the list
+     */
+    public Merge removeFromWorkList() {
+        if (workListIndex != 0) {
+            return workList[--workListIndex];
+        }
+        return null;
+    }
+
+    /**
+     * Checks whether the list is empty.
+     * @return {@code true} if this list is empty
+     */
+    public boolean isEmpty() {
+        return workListIndex == 0;
+    }
+
+    private void allocate() {
+        workList = new Merge[5];
+        workListNumbers = new int[5];
+    }
+
+    private void grow() {
+        int prevLength = workList.length;
+        Merge[] nworkList = new Merge[prevLength * 3];
+        System.arraycopy(workList, 0, nworkList, 0, prevLength);
+        workList = nworkList;
+
+        int[] nworkListNumbers = new int[prevLength * 3];
+        System.arraycopy(workListNumbers, 0, nworkListNumbers, 0, prevLength);
+        workListNumbers = nworkListNumbers;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/GraphUtil.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,346 @@
+/*
+ * 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.max.graal.compiler.util;
+
+import java.util.*;
+import java.util.Map.Entry;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.ir.Phi.PhiType;
+import com.oracle.max.graal.compiler.observer.*;
+import com.oracle.max.graal.compiler.value.*;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.graph.NodeWorkList.*;
+
+public class GraphUtil {
+
+    public static interface ColoringLambda<T> {
+        T color(Iterable<T> incomming, Merge merge);
+        T danglingColor(Iterable<T> incomming, Merge merge);
+    }
+
+    /**
+     * colors down, applying the lambda at merge points, starting at the pre-colored points.
+     */
+    public static <T> void colorCFGDown(NodeMap<T> colors, ColoringLambda<T> lambda) {
+        Set<Merge> delayed = new HashSet<Merge>();
+        Set<Node> currentPoints = new HashSet<Node>();
+        Set<Node> otherPoints = new HashSet<Node>();
+        Set<Merge> otherMerges = new HashSet<Merge>();
+        for (Entry<Node, T> entry : colors.entries()) {
+            currentPoints.add(entry.getKey());
+        }
+        ArrayList<T> incomming = new ArrayList<T>(2);
+        while (!currentPoints.isEmpty()) {
+            for (Node node : currentPoints) {
+                otherMerges.addAll(colorCFGDownToMerge(node, colors.get(node), colors));
+            }
+            for (Merge merge : otherMerges) {
+                incomming.clear();
+                for (EndNode end : merge.cfgPredecessors()) {
+                    incomming.add(colors.get(end));
+                }
+                T color = lambda.color(incomming, merge);
+                if (color != null) {
+                    colors.set(merge, color);
+                    colors.set(merge.next(), color);
+                    otherPoints.add(merge.next());
+                    delayed.remove(merge);
+                } else {
+                    delayed.add(merge);
+                }
+            }
+            Set<Node> tmp = currentPoints;
+            currentPoints = otherPoints;
+            otherPoints = tmp;
+            otherPoints.clear();
+            otherMerges.clear();
+        }
+        for (Merge merge : delayed) {
+            T color = lambda.danglingColor(incomming, merge);
+            if (color != null) {
+                colors.set(merge, color);
+            }
+        }
+    }
+
+    private static <T> Collection<Merge> colorCFGDownToMerge(Node from, T color, NodeMap<T> colors) {
+        //System.out.println("colorCFGDownToMerge(" + from + ", " + color + ", colors)");
+        NodeFlood work = from.graph().createNodeFlood();
+        Collection<Merge> merges = new LinkedList<Merge>();
+        work.add(from);
+        for (Node node : work) {
+            //System.out.println("colorToMerge : work on " + node);
+            Node current = node;
+            while (current != null) {
+                //System.out.println("colorToMerge : current " + current);
+                if (current instanceof Merge) {
+                    merges.add((Merge) current);
+                    break;
+                }
+                colors.set(current, color);
+                if (current instanceof FixedNodeWithNext && !(current instanceof AbstractVectorNode) && !(current instanceof Invoke && ((Invoke) current).exceptionEdge() != null)) {
+                    current = ((FixedNodeWithNext) current).next();
+                } else if (current instanceof EndNode) {
+                    current = ((EndNode) current).merge();
+                } else {
+                    if (current instanceof ControlSplit) {
+                        for (Node sux : current.cfgSuccessors()) {
+                            work.add(sux);
+                        }
+                    } else if (current instanceof Invoke && ((Invoke) current).exceptionEdge() != null) {
+                        Invoke invoke = (Invoke) current;
+                        work.add(invoke.next());
+                        work.add(invoke.exceptionEdge());
+                    } else if (current instanceof AbstractVectorNode) {
+                        for (Node usage : current.usages()) {
+                            work.add(usage);
+                        }
+                        work.add(((AbstractVectorNode) current).next());
+                    }
+                    current = null;
+                }
+            }
+        }
+        //System.out.println("return " + merges);
+        return merges;
+    }
+
+    public static interface ColorSplitingLambda<T> {
+        void fixSplit(Node oldNode, Node newNode, T color);
+        void fixNode(Node node, T color);
+        Value fixPhiInput(Value input, T color);
+        boolean explore(Node n);
+        List<T> parentColors(T color);
+        Merge merge(T color);
+    }
+
+    // TODO (gd) rework that code around Phi handling : too complicated
+    public static <T> void splitFromColoring(NodeMap<T> coloring, ColorSplitingLambda<T> lambda) {
+        Map<Node, T> internalColoring = new HashMap<Node, T>();
+        NodeWorkList work = coloring.graph().createNodeWorkList();
+        for (Entry<Node, T> entry : coloring.entries()) {
+            T color = entry.getValue();
+            Node node = entry.getKey();
+            work.add(node);
+            internalColoring.put(node, color);
+        }
+        Set<T> colors = new HashSet<T>();
+        try {
+            for (Node node : work) {
+                //System.out.println("Split : work on " + node);
+                if (node instanceof Phi) {
+                    Phi phi = (Phi) node;
+                    Merge merge = phi.merge();
+                    for (int i = 0; i < phi.valueCount(); i++) {
+                        Value v = phi.valueAt(i);
+                        if (v != null) {
+                            T color = internalColoring.get(merge.phiPredecessorAt(i));
+                            if (color != null) {
+                                Value replace = lambda.fixPhiInput(v, color);
+                                if (replace != v) {
+                                    phi.setValueAt(i, replace);
+                                } else {
+                                    if (lambda.explore(v) && coloring.get(v) == null && !work.isNew(v)) {
+                                        //System.out.println("Split : Add input " + input + " to work from " + node);
+                                        work.add(v);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                } else {
+                    boolean delay = false;
+                    colors.clear();
+                    T originalColoringColor = coloring.get(node);
+                    if (originalColoringColor == null && internalColoring.get(node) != null) {
+                        //System.out.println("Split : ori == null && intern != null -> continue");
+                        continue;
+                    }
+                    if (originalColoringColor == null) {
+                        for (Node usage : node.dataUsages()) {
+                            if (usage instanceof Phi) {
+                                Phi phi = (Phi) usage;
+                                Merge merge = phi.merge();
+                                //System.out.println("Split merge : " + merge + ".endCount = " + merge.endCount() + " phi " + phi + ".valueCount : " + phi.valueCount());
+                                for (int i = 0; i < phi.valueCount(); i++) {
+                                    Value v = phi.valueAt(i);
+                                    if (v == node) {
+                                        T color = internalColoring.get(merge.phiPredecessorAt(i));
+                                        if (color != null) {
+                                            colors.add(color);
+                                        }
+                                    }
+                                }
+                            } else {
+                                T color = internalColoring.get(usage);
+                                if (color == null) {
+                                    //System.out.println("Split : color from " + usage + " is null : " + (lambda.explore(usage) ? "Should be colored" : "Should be white"));
+                                    if (lambda.explore(usage)) {
+                                        delay = true;
+                                        break;
+                                    }
+                                } else {
+                                    colors.add(color);
+                                }
+                            }
+                        }
+                        if (delay) {
+                            //System.out.println("Split : delay");
+                            work.addAgain(node);
+                            continue;
+                        }
+                    } else {
+                        colors.add(originalColoringColor);
+                    }
+                    if (colors.size() == 1) {
+                        //System.out.println("Split : 1 color, coloring, fixing");
+                        T color = colors.iterator().next();
+                        internalColoring.put(node, color);
+                        lambda.fixNode(node, color);
+                    } else {
+                        Map<T, Node> newNodes = new HashMap<T, Node>();
+                        Queue<T> colorQueue = new LinkedList<T>(colors);
+                        while (!colorQueue.isEmpty()) {
+                            T color = colorQueue.poll();
+                            List<T> parentColors = lambda.parentColors(color);
+                            Node newNode;
+                            if (parentColors.size() > 1 && !(node instanceof FrameState) && colors.containsAll(parentColors)) {
+                                boolean ready = true;
+                                for (T parentColor : parentColors) {
+                                    if (newNodes.get(parentColor) == null) {
+                                        ready = false;
+                                        break;
+                                    }
+                                }
+                                if (!ready) {
+                                    colorQueue.offer(color);
+                                    continue;
+                                }
+                                Phi phi = new Phi(((Value) node).kind, lambda.merge(color), PhiType.Value, node.graph());
+                                for (T parentColor : parentColors) {
+                                    Node input = newNodes.get(parentColor);
+                                    phi.addInput(input);
+                                }
+                                newNode = phi;
+                            } else {
+                                newNode = node.copy();
+                                for (int i = 0; i < node.inputs().size(); i++) {
+                                    Node input = node.inputs().get(i);
+                                    newNode.inputs().setOrExpand(i, input);
+                                }
+                                for (int i = 0; i < node.successors().size(); i++) {
+                                    Node input = node.successors().get(i);
+                                    newNode.successors().setOrExpand(i, input);
+                                }
+                                internalColoring.put(newNode, color);
+                                lambda.fixSplit(node, newNode, color);
+                            }
+                            newNodes.put(color, newNode);
+                            LinkedList<Node> dataUsages = new LinkedList<Node>();
+                            for (Node usage : node.dataUsages()) {
+                                dataUsages.add(usage);
+                            }
+                            for (Node usage : dataUsages) {
+                                if (usage instanceof Phi) {
+                                    Phi phi = (Phi) usage;
+                                    Merge merge = phi.merge();
+                                    for (int i = 0; i < phi.valueCount(); i++) {
+                                        Value v = phi.valueAt(i);
+                                        if (v == node) {
+                                            T uColor = internalColoring.get(merge.endAt(i));
+                                            if (uColor == color) {
+                                                phi.setValueAt(i, (Value) newNode);
+                                            }
+                                        }
+                                    }
+                                } else {
+                                    T uColor = internalColoring.get(usage);
+                                    if (uColor == color) {
+                                        usage.inputs().replace(node, newNode);
+                                    }
+                                }
+                            }
+                        }
+                        lambda.fixNode(node, null /*white*/);
+                    }
+                    if (node instanceof StateSplit) {
+                        FrameState stateAfter = ((StateSplit) node).stateAfter();
+                        if (stateAfter != null && lambda.explore(stateAfter) && !work.isNew(stateAfter)) {
+                            //System.out.println("Split : Add framestate to work");
+                            if (!(node instanceof Merge && coloring.get(((Merge) node).next()) == null)) { // not dangling colored merge
+                                work.add(stateAfter);
+                            }
+                        }
+                    }
+
+                    if (node instanceof Merge) {
+                        for (Node usage : node.usages()) {
+                            if (!work.isNew(usage)) {
+                                work.add(usage);
+                            }
+                        }
+                    }
+
+                    if (node instanceof LoopEnd) {
+                        work.add(((LoopEnd) node).loopBegin());
+                    }
+
+                    for (Node input : node.dataInputs()) {
+                        if (lambda.explore(input) && coloring.get(input) == null && !work.isNew(input)) {
+                            //System.out.println("Split : Add input " + input + " to work from " + node);
+                            work.add(input);
+                        }
+                    }
+                }
+            }
+        } catch (InfiniteWorkException re) {
+            System.out.println("Infinite work, current queue :");
+            for (Node n : work) {
+                System.out.println(" - " + n);
+            }
+            GraalCompilation compilation = GraalCompilation.compilation();
+            if (compilation.compiler.isObserved()) {
+                NodeMap<T> debugColoring = coloring.graph().createNodeMap();
+                for (Entry<Node, T> entry : internalColoring.entrySet()) {
+                    debugColoring.set(entry.getKey(), entry.getValue());
+                }
+                Map<String, Object> debug = new HashMap<String, Object>();
+                debug.put("split", debugColoring);
+                compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "RuntimeException in split", coloring.graph(), true, false, true, debug));
+            }
+            throw re;
+        }
+        GraalCompilation compilation = GraalCompilation.compilation();
+        if (compilation.compiler.isObserved()) {
+            NodeMap<T> debugColoring = coloring.graph().createNodeMap();
+            for (Entry<Node, T> entry : internalColoring.entrySet()) {
+                debugColoring.set(entry.getKey(), entry.getValue());
+            }
+            Map<String, Object> debug = new HashMap<String, Object>();
+            debug.put("split", debugColoring);
+            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "Split end!!", coloring.graph(), true, false, debug));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/IntList.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2010, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.util;
+
+import java.util.*;
+
+/**
+ * An expandable and indexable list of {@code int}s.
+ *
+ * This class avoids the boxing/unboxing incurred by {@code ArrayList<Integer>}.
+ *
+ * @author Doug Simon
+ */
+public final class IntList {
+
+    private int[] array;
+    private int size;
+
+    /**
+     * Creates an int list with a specified initial capacity.
+     *
+     * @param initialCapacity
+     */
+    public IntList(int initialCapacity) {
+        array = new int[initialCapacity];
+    }
+
+    /**
+     * Creates an int list with a specified initial array.
+     *
+     * @param array the initial array used for the list (no copy is made)
+     * @param initialSize the initial {@linkplain #size() size} of the list (must be less than or equal to {@code array.length}
+     */
+    public IntList(int[] array, int initialSize) {
+        assert initialSize <= array.length;
+        this.array = array;
+        this.size = initialSize;
+    }
+
+    /**
+     * Makes a new int list by copying a range from a given int list.
+     *
+     * @param other the list from which a range of values is to be copied into the new list
+     * @param startIndex the index in {@code other} at which to start copying
+     * @param length the number of values to copy from {@code other}
+     * @return a new int list whose {@linkplain #size() size} and capacity is {@code length}
+     */
+    public static IntList copy(IntList other, int startIndex, int length) {
+        return copy(other, startIndex, length, length);
+    }
+
+    /**
+     * Makes a new int list by copying a range from a given int list.
+     *
+     * @param other the list from which a range of values is to be copied into the new list
+     * @param startIndex the index in {@code other} at which to start copying
+     * @param length the number of values to copy from {@code other}
+     * @param initialCapacity the initial capacity of the new int list (must be greater or equal to {@code length})
+     * @return a new int list whose {@linkplain #size() size} is {@code length}
+     */
+    public static IntList copy(IntList other, int startIndex, int length, int initialCapacity) {
+        assert initialCapacity >= length : "initialCapacity < length";
+        int[] array = new int[initialCapacity];
+        System.arraycopy(other.array, startIndex, array, 0, length);
+        return new IntList(array, length);
+    }
+
+    public int size() {
+        return size;
+    }
+
+    /**
+     * Appends a value to the end of this list, increasing its {@linkplain #size() size} by 1.
+     *
+     * @param value the value to append
+     */
+    public void add(int value) {
+        if (size == array.length) {
+            int newSize = (size * 3) / 2 + 1;
+            array = Arrays.copyOf(array, newSize);
+        }
+        array[size++] = value;
+    }
+
+    /**
+     * Gets the value in this list at a given index.
+     *
+     * @param index the index of the element to return
+     * @throws IndexOutOfBoundsException if {@code index < 0 || index >= size()}
+     */
+    public int get(int index) {
+        if (index >= size) {
+            throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
+        }
+        return array[index];
+    }
+
+    /**
+     * Sets the size of this list to 0.
+     */
+    public void clear() {
+        size = 0;
+    }
+
+    /**
+     * Sets a value at a given index in this list.
+     *
+     * @param index the index of the element to update
+     * @param value the new value of the element
+     * @throws IndexOutOfBoundsException if {@code index < 0 || index >= size()}
+     */
+    public void set(int index, int value) {
+        if (index >= size) {
+            throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
+        }
+        array[index] = value;
+    }
+
+    /**
+     * Adjusts the {@linkplain #size() size} of this int list.
+     *
+     * If {@code newSize < size()}, the size is changed to {@code newSize}.
+     * If {@code newSize > size()}, sufficient 0 elements are {@linkplain #add(int) added}
+     * until {@code size() == newSize}.
+     *
+     * @param newSize the new size of this int list
+     */
+    public void setSize(int newSize) {
+        if (newSize < size) {
+            size = newSize;
+        } else if (newSize > size) {
+            array = Arrays.copyOf(array, newSize);
+        }
+    }
+
+    @Override
+    public String toString() {
+        if (array.length == size) {
+            return Arrays.toString(array);
+        }
+        return Arrays.toString(Arrays.copyOf(array, size));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/LoopUtil.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,958 @@
+/*
+ * 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.max.graal.compiler.util;
+
+import java.util.*;
+import java.util.Map.Entry;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.ir.Phi.*;
+import com.oracle.max.graal.compiler.observer.*;
+import com.oracle.max.graal.compiler.schedule.*;
+import com.oracle.max.graal.compiler.util.GraphUtil.ColorSplitingLambda;
+import com.oracle.max.graal.compiler.util.GraphUtil.ColoringLambda;
+import com.oracle.max.graal.compiler.value.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+public class LoopUtil {
+
+    public static class Loop {
+        private final LoopBegin loopBegin;
+        private NodeBitMap cfgNodes;
+        private Loop parent;
+        private NodeBitMap exits;
+        private NodeBitMap inOrBefore;
+        private NodeBitMap inOrAfter;
+        private NodeBitMap nodes;
+        public Loop(LoopBegin loopBegin, NodeBitMap nodes, NodeBitMap exits) {
+            this.loopBegin = loopBegin;
+            this.cfgNodes = nodes;
+            this.exits = exits;
+        }
+
+        public LoopBegin loopBegin() {
+            return loopBegin;
+        }
+
+        public NodeBitMap cfgNodes() {
+            return cfgNodes;
+        }
+
+        public NodeBitMap nodes() {
+            if (nodes == null) {
+                nodes = loopBegin().graph().createNodeBitMap();
+                nodes.setUnion(inOrAfter());
+                nodes.setIntersect(inOrBefore());
+            }
+            return nodes;
+        }
+
+        public Loop parent() {
+            return parent;
+        }
+
+        public NodeBitMap exits() {
+            return exits;
+        }
+
+        public void setParent(Loop parent) {
+            this.parent = parent;
+        }
+
+        public boolean isChild(Loop loop) {
+            return loop.parent != null && (loop.parent == this || loop.parent.isChild(this));
+        }
+
+        public NodeBitMap inOrAfter() {
+            if (inOrAfter == null) {
+                inOrAfter = LoopUtil.inOrAfter(this);
+            }
+            return inOrAfter;
+        }
+
+        public NodeBitMap inOrBefore() {
+            if (inOrBefore == null) {
+                inOrBefore = LoopUtil.inOrBefore(this, inOrAfter());
+            }
+            return inOrBefore;
+        }
+
+        public void invalidateCached() {
+            inOrAfter = null;
+            inOrBefore = null;
+            nodes = null;
+        }
+
+        @Override
+        public String toString() {
+            return "Loop #" + loopBegin().id();
+        }
+    }
+
+    private static class PeelingResult {
+        public final FixedNode begin;
+        public final FixedNode end;
+        public final NodeMap<StateSplit> exits;
+        public final NodeBitMap unaffectedExits;
+        public final NodeMap<Placeholder> phis;
+        public final NodeMap<Node> phiInits;
+        public final NodeMap<Node> dataOut;
+        public final NodeBitMap exitFrameStates;
+        public final NodeBitMap peeledNodes;
+        public PeelingResult(FixedNode begin, FixedNode end, NodeMap<StateSplit> exits, NodeMap<Placeholder> phis, NodeMap<Node> phiInits, NodeMap<Node> dataOut, NodeBitMap unaffectedExits, NodeBitMap exitFrameStates, NodeBitMap peeledNodes) {
+            this.begin = begin;
+            this.end = end;
+            this.exits = exits;
+            this.phis = phis;
+            this.phiInits = phiInits;
+            this.dataOut = dataOut;
+            this.unaffectedExits = unaffectedExits;
+            this.exitFrameStates = exitFrameStates;
+            this.peeledNodes = peeledNodes;
+        }
+    }
+
+    public static List<Loop> computeLoops(Graph graph) {
+        List<Loop> loops = new LinkedList<LoopUtil.Loop>();
+        for (LoopBegin loopBegin : graph.getNodes(LoopBegin.class)) {
+            NodeBitMap cfgNodes = markUpCFG(loopBegin, loopBegin.loopEnd()); // computeLoopNodes(loopBegin);
+            cfgNodes.mark(loopBegin);
+            NodeBitMap exits = computeLoopExits(loopBegin, cfgNodes);
+            loops.add(new Loop(loopBegin, cfgNodes, exits));
+        }
+        for (Loop loop : loops) {
+            for (Loop other : loops) {
+                if (other != loop && other.cfgNodes().isMarked(loop.loopBegin())) {
+                    if (loop.parent() == null || loop.parent().cfgNodes().isMarked(other.loopBegin())) {
+                        loop.setParent(other);
+                    }
+                }
+            }
+        }
+        return loops;
+    }
+
+    public static NodeBitMap computeLoopExits(LoopBegin loopBegin, NodeBitMap cfgNodes) {
+        Graph graph = loopBegin.graph();
+        NodeBitMap exits = graph.createNodeBitMap();
+        for (Node n : cfgNodes) {
+            if (IdentifyBlocksPhase.trueSuccessorCount(n) > 1) {
+                for (Node sux : n.cfgSuccessors()) {
+                    if (!cfgNodes.isMarked(sux) && sux instanceof FixedNode) {
+                        exits.mark(sux);
+                    }
+                }
+            }
+        }
+        return exits;
+    }
+
+    private static boolean recurse = false;
+    public static NodeBitMap computeLoopNodesFrom(Loop loop, FixedNode from) {
+        LoopBegin loopBegin = loop.loopBegin();
+        NodeBitMap loopNodes = markUpCFG(loopBegin, from);
+        loopNodes.mark(loopBegin);
+        NodeBitMap inOrAfter = inOrAfter(loop, loopNodes, false);
+        NodeBitMap inOrBefore = inOrBefore(loop, inOrAfter, loopNodes, false);
+        if (!recurse) {
+            recurse = true;
+            GraalCompilation compilation = GraalCompilation.compilation();
+            if (compilation.compiler.isObserved()) {
+                Map<String, Object> debug = new HashMap<String, Object>();
+                debug.put("loopNodes", loopNodes);
+                debug.put("inOrAfter", inOrAfter);
+                debug.put("inOrBefore", inOrBefore);
+                compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "Compute loop nodes loop#" + loopBegin.id(), loopBegin.graph(), true, false, debug));
+            }
+            recurse = false;
+        }
+        inOrAfter.setIntersect(inOrBefore);
+        loopNodes.setUnion(inOrAfter);
+        if (from == loopBegin.loopEnd()) { // fill the Loop cache value for loop nodes this is correct even if after/before were partial
+            loop.nodes = loopNodes;
+        }
+        return loopNodes;
+    }
+
+    public static NodeBitMap markUpCFG(LoopBegin loopBegin) {
+        return markUpCFG(loopBegin, loopBegin.loopEnd());
+    }
+
+    public static NodeBitMap markUpCFG(LoopBegin loopBegin, FixedNode from) {
+        NodeFlood workCFG = loopBegin.graph().createNodeFlood();
+        workCFG.add(from);
+        NodeBitMap loopNodes = loopBegin.graph().createNodeBitMap();
+        for (Node n : workCFG) {
+            if (n == loopBegin) {
+                continue;
+            }
+            loopNodes.mark(n);
+            if (n instanceof LoopBegin) {
+                workCFG.add(((LoopBegin) n).loopEnd());
+            }
+            for (Node pred : n.cfgPredecessors()) {
+                workCFG.add(pred);
+            }
+        }
+        return loopNodes;
+    }
+
+    public static void inverseLoop(Loop loop, If split) {
+        assert loop.cfgNodes().isMarked(split);
+        FixedNode noExit = split.trueSuccessor();
+        FixedNode exit = split.falseSuccessor();
+        if (loop.cfgNodes().isMarked(exit) && !loop.cfgNodes().isMarked(noExit)) {
+            FixedNode tmp = noExit;
+            noExit = exit;
+            exit = tmp;
+        }
+        assert !loop.cfgNodes().isMarked(exit);
+        assert loop.cfgNodes().isMarked(noExit);
+
+        PeelingResult peeling = preparePeeling(loop, split);
+        rewireInversion(peeling, loop, split);
+
+        // move peeled part to the end
+        LoopBegin loopBegin = loop.loopBegin();
+        LoopEnd loopEnd = loopBegin.loopEnd();
+        FixedNode lastNode = (FixedNode) loopEnd.singlePredecessor();
+        if (loopBegin.next() != lastNode) {
+            lastNode.successors().replace(loopEnd, loopBegin.next());
+            loopBegin.setNext(noExit);
+            split.successors().replace(noExit, loopEnd);
+        }
+
+        //rewire phi usage in peeled part
+        int backIndex = loopBegin.phiPredecessorIndex(loopBegin.loopEnd());
+        for (Phi phi : loopBegin.phis()) {
+            Value backValue = phi.valueAt(backIndex);
+            if (loop.nodes().isMarked(backValue) && peeling.peeledNodes.isNotNewNotMarked(backValue)) {
+                List<Node> usages = new ArrayList<Node>(phi.usages());
+                for (Node usage : usages) {
+                    if (peeling.peeledNodes.isNotNewMarked(usage)) {
+                        usage.inputs().replace(phi, backValue);
+                    }
+                }
+            }
+        }
+
+        loop.invalidateCached();
+
+        // update parents
+        Loop parent = loop.parent();
+        while (parent != null) {
+            parent.cfgNodes = markUpCFG(parent.loopBegin, parent.loopBegin.loopEnd());
+            parent.invalidateCached();
+            parent.exits = computeLoopExits(parent.loopBegin, parent.cfgNodes);
+            parent = parent.parent;
+        }
+
+        GraalMetrics.LoopsInverted++;
+    }
+
+    public static void peelLoop(Loop loop) {
+        LoopEnd loopEnd = loop.loopBegin().loopEnd();
+        PeelingResult peeling = preparePeeling(loop, loopEnd);
+        GraalCompilation compilation = GraalCompilation.compilation();
+        if (compilation.compiler.isObserved()) {
+            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After peeling preparation", loopEnd.graph(), true, false));
+        }
+        /*System.out.println("Peeling : ");
+        System.out.println(" begin = " + peeling.begin);
+        System.out.println(" end = " + peeling.end);
+        System.out.println(" Phis :");
+        for (Entry<Node, Placeholder> entry : peeling.phis.entries()) {
+            System.out.println("  - " + entry.getKey() + " -> " + entry.getValue());
+        }
+        System.out.println(" Exits :");
+        for (Entry<Node, StateSplit> entry : peeling.exits.entries()) {
+            System.out.println("  - " + entry.getKey() + " -> " + entry.getValue());
+        }
+        System.out.println(" PhiInits :");
+        for (Entry<Node, Node> entry : peeling.phiInits.entries()) {
+            System.out.println("  - " + entry.getKey() + " -> " + entry.getValue());
+        }
+        System.out.println(" DataOut :");
+        for (Entry<Node, Node> entry : peeling.dataOut.entries()) {
+            System.out.println("  - " + entry.getKey() + " -> " + entry.getValue());
+        }*/
+        rewirePeeling(peeling, loop);
+        /*if (compilation.compiler.isObserved()) {
+            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After rewirePeeling", loopEnd.graph(), true, false));
+        }*/
+        loop.invalidateCached();
+        // update parents
+        Loop parent = loop.parent();
+        while (parent != null) {
+            parent.cfgNodes = markUpCFG(parent.loopBegin, parent.loopBegin.loopEnd());
+            parent.invalidateCached();
+            parent.exits = computeLoopExits(parent.loopBegin, parent.cfgNodes);
+            parent = parent.parent;
+        }
+        GraalMetrics.LoopsPeeled++;
+    }
+
+    private static void rewireInversion(PeelingResult peeling, Loop loop, FixedNode from) {
+        rewirePeeling(peeling, loop, from, true);
+    }
+
+    private static void rewirePeeling(PeelingResult peeling, Loop loop) {
+        rewirePeeling(peeling, loop, loop.loopBegin().loopEnd(), false);
+    }
+
+    private static void rewirePeeling(PeelingResult peeling, Loop loop, FixedNode from, boolean inversion) {
+        LoopBegin loopBegin = loop.loopBegin();
+        Graph graph = loopBegin.graph();
+        Node loopPred = loopBegin.singlePredecessor();
+        loopPred.successors().replace(loopBegin.forwardEdge(), peeling.begin);
+        NodeBitMap loopNodes = loop.cfgNodes();
+        Node originalLast = from;
+        if (originalLast == loopBegin.loopEnd()) {
+            originalLast = loopBegin.loopEnd().singlePredecessor();
+        }
+        int size = originalLast.successors().size();
+        boolean found = false;
+        for (int i = 0; i < size; i++) {
+            Node sux = originalLast.successors().get(i);
+            if (sux == null) {
+                continue;
+            }
+            if (loopNodes.isMarked(sux)) {
+                assert !found;
+                peeling.end.successors().set(i, loopBegin.forwardEdge());
+                found = true;
+            }
+        }
+        assert found;
+        int phiInitIndex = loopBegin.phiPredecessorIndex(loopBegin.forwardEdge());
+        for (Entry<Node, Placeholder> entry : peeling.phis.entries()) {
+            Phi phi = (Phi) entry.getKey();
+            Placeholder p = entry.getValue();
+            Value init = phi.valueAt(phiInitIndex);
+            p.replaceAndDelete(init);
+            for (Entry<Node, Node> dataEntry : peeling.dataOut.entries()) {
+                if (dataEntry.getValue() == p) {
+                    dataEntry.setValue(init);
+                    //System.out.println("Patch dataOut : " + dataEntry.getKey() + " -> " + dataEntry.getValue());
+                }
+            }
+        }
+        for (Entry<Node, Node> entry : peeling.phiInits.entries()) {
+            Phi phi = (Phi) entry.getKey();
+            Node newInit = entry.getValue();
+            phi.setValueAt(phiInitIndex, (Value) newInit);
+        }
+
+        if (from == loopBegin.loopEnd()) {
+            for (LoopCounter counter : loopBegin.counters()) {
+                counter.setInit(new IntegerAdd(counter.kind, counter.init(), counter.stride(), graph));
+            }
+        }
+        NodeMap<NodeMap<Value>> newExitValues = graph.createNodeMap();
+        List<Node> exitPoints = new LinkedList<Node>();
+        for (Node exit : peeling.unaffectedExits) {
+            exitPoints.add(exit);
+        }
+
+        for (Entry<Node, StateSplit> entry : peeling.exits.entries()) {
+            StateSplit original = (StateSplit) entry.getKey();
+            StateSplit newExit = entry.getValue();
+            EndNode oEnd = new EndNode(graph);
+            EndNode nEnd = new EndNode(graph);
+            Merge merge = new Merge(graph);
+            FrameState originalState = original.stateAfter();
+            merge.addEnd(nEnd);
+            merge.addEnd(oEnd);
+            merge.setStateAfter(originalState.duplicate(originalState.bci, true));
+            merge.setNext(original.next());
+            original.setNext(oEnd);
+            newExit.setNext(nEnd);
+            exitPoints.add(original);
+            exitPoints.add(newExit);
+        }
+
+        int phiBackIndex = loopBegin.phiPredecessorIndex(loopBegin.loopEnd());
+        for (Entry<Node, StateSplit> entry : peeling.exits.entries()) {
+            StateSplit original = (StateSplit) entry.getKey();
+            EndNode oEnd = (EndNode) original.next();
+            Merge merge = oEnd.merge();
+            EndNode nEnd = merge.endAt(1 - merge.phiPredecessorIndex(oEnd));
+            Node newExit = nEnd.singlePredecessor();
+            for (Entry<Node, Node> dataEntry : peeling.dataOut.entries()) {
+                Node originalValue = dataEntry.getKey();
+                Node newValue = dataEntry.getValue();
+                NodeMap<Value> phiMap = newExitValues.get(originalValue);
+                if (phiMap == null) {
+                    phiMap = graph.createNodeMap();
+                    newExitValues.set(originalValue, phiMap);
+                }
+                Value backValue = null;
+                if (inversion && originalValue instanceof Phi && ((Phi) originalValue).merge() == loopBegin) {
+                    backValue = ((Phi) originalValue).valueAt(phiBackIndex);
+                    if (peeling.peeledNodes.isNotNewMarked(backValue)) {
+                        backValue = null;
+                    }
+                }
+                if (backValue != null) {
+                    phiMap.set(original, backValue);
+                } else {
+                    phiMap.set(original, (Value) originalValue);
+                }
+                phiMap.set(newExit, (Value) newValue);
+            }
+        }
+
+        if (inversion) {
+            // rewire dataOut in non-peeled body
+            NodeBitMap exitMergesPhis = graph.createNodeBitMap();
+            for (Entry<Node, StateSplit> entry : peeling.exits.entries()) {
+                StateSplit newExit = entry.getValue();
+                Merge merge = ((EndNode) newExit.next()).merge();
+                exitMergesPhis.markAll(merge.phis());
+            }
+            for (Entry<Node, Node> entry : peeling.dataOut.entries()) {
+                Value originalValue = (Value) entry.getKey();
+                if (originalValue instanceof Phi && ((Phi) originalValue).merge() == loopBegin) {
+                    continue;
+                }
+                Value newValue = (Value) entry.getValue();
+                Phi phi = null;
+                List<Node> usages = new ArrayList<Node>(originalValue.usages());
+                for (Node usage : usages) {
+                    if (exitMergesPhis.isMarked(usage) || (
+                                    loop.nodes().isNotNewMarked(usage)
+                                    && peeling.peeledNodes.isNotNewNotMarked(usage)
+                                    && !(usage instanceof Phi && ((Phi) usage).merge() == loopBegin))
+                                    && !(usage instanceof FrameState && ((FrameState) usage).block() == loopBegin)) {
+                        if (phi == null) {
+                            phi = new Phi(originalValue.kind, loopBegin, PhiType.Value, graph);
+                            phi.addInput(newValue);
+                            phi.addInput(originalValue);
+                            NodeMap<Value> exitMap = newExitValues.get(originalValue);
+                            for (Node exit : peeling.unaffectedExits) {
+                                exitMap.set(exit, phi);
+                            }
+                        }
+                        usage.inputs().replace(originalValue, phi);
+                    }
+                }
+            }
+        }
+
+        for (Entry<Node, NodeMap<Value>> entry : newExitValues.entries()) {
+            Value original = (Value) entry.getKey();
+            NodeMap<Value> pointToValue = entry.getValue();
+            for (Node exit : exitPoints) {
+                Node valueAtExit = pointToValue.get(exit);
+                if (valueAtExit == null) {
+                    pointToValue.set(exit, original);
+                }
+            }
+        }
+
+        replaceValuesAtLoopExits(newExitValues, loop, exitPoints, peeling.exitFrameStates);
+    }
+
+    private static void replaceValuesAtLoopExits(final NodeMap<NodeMap<Value>> newExitValues, Loop loop, List<Node> exitPoints, final NodeBitMap exitFrameStates) {
+        Graph graph = loop.loopBegin().graph();
+        final NodeMap<Node> colors = graph.createNodeMap();
+
+        // prepare inital colors
+        for (Node exitPoint : exitPoints) {
+            colors.set(exitPoint, exitPoint);
+        }
+
+        /*System.out.println("newExitValues");
+        for (Entry<Node, NodeMap<Value>> entry : newExitValues.entries()) {
+            System.out.println(" - " + entry.getKey() + " :");
+            for (Entry<Node, Value> entry2 : entry.getValue().entries()) {
+                System.out.println("    + " + entry2.getKey() + " -> " + entry2.getValue());
+            }
+        }*/
+
+        // color
+        GraphUtil.colorCFGDown(colors, new ColoringLambda<Node>() {
+            @Override
+            public Node color(Iterable<Node> incomming, Merge merge) {
+                Node color = null;
+                for (Node c : incomming) {
+                    if (c == null) {
+                        return null;
+                    }
+                    if (color == null) {
+                        color = c;
+                    } else if (color != c) {
+                        return merge;
+                    }
+                }
+                return color;
+            }
+            @Override
+            public Node danglingColor(Iterable<Node> incomming, Merge merge) {
+                Node color = null;
+                for (Node c : incomming) {
+                    if (color == null) {
+                        color = c;
+                    } else if (color != c) {
+                        return merge;
+                    }
+                }
+                assert color != null;
+                return color;
+            }
+        });
+
+
+        loop.invalidateCached();
+        final NodeBitMap inOrBefore = loop.inOrBefore();
+
+        GraalCompilation compilation = GraalCompilation.compilation();
+        if (compilation.compiler.isObserved()) {
+            Map<String, Object> debug = new HashMap<String, Object>();
+            debug.put("loopExits", colors);
+            debug.put("inOrBefore", inOrBefore);
+            debug.put("inOrAfter", loop.inOrAfter());
+            debug.put("nodes", loop.nodes());
+            debug.put("exitFrameStates", exitFrameStates);
+            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After coloring", graph, true, false, debug));
+        }
+
+        GraphUtil.splitFromColoring(colors, new ColorSplitingLambda<Node>(){
+            @Override
+            public void fixSplit(Node oldNode, Node newNode, Node color) {
+                assert color != null;
+                this.fixNode(newNode, color);
+            }
+            private Value getValueAt(Node point, NodeMap<Value> valueMap, CiKind kind) {
+                Value value = valueMap.get(point);
+                if (value != null) {
+                    //System.out.println("getValueAt(" + point + ", valueMap, kind) = (cached) " + value);
+                    return value;
+                }
+                Merge merge = (Merge) point;
+                ArrayList<Value> values = new ArrayList<Value>(merge.phiPredecessorCount());
+                Value v = null;
+                boolean createPhi = false;
+                for (EndNode end : merge.cfgPredecessors()) {
+                    Value valueAt = getValueAt(colors.get(end), valueMap, kind);
+                    if (v == null) {
+                        v = valueAt;
+                    } else if (v != valueAt) {
+                        createPhi = true;
+                    }
+                    values.add(valueAt);
+                }
+                if (createPhi) {
+                    Phi phi = new Phi(kind, merge, PhiType.Value, merge.graph());
+                    valueMap.set(point, phi);
+                    for (EndNode end : merge.cfgPredecessors()) {
+                        phi.addInput(getValueAt(colors.get(end), valueMap, kind));
+                    }
+                    //System.out.println("getValueAt(" + point + ", valueMap, kind) = (new-phi) " + phi);
+                    return phi;
+                } else {
+                    assert v != null;
+                    valueMap.set(point, v);
+                    //System.out.println("getValueAt(" + point + ", valueMap, kind) = (unique) " + v);
+                    return v;
+                }
+            }
+            @Override
+            public boolean explore(Node n) {
+                /*System.out.println("Explore " + n + "?");
+                System.out.println(" - exitFS : " + (!exitFrameStates.isNew(n) && exitFrameStates.isMarked(n)));
+                System.out.println(" - !inOrBefore : " + (!inOrBefore.isNew(n) && !inOrBefore.isMarked(n)));
+                System.out.println(" - inputs > 0 : " + (n.inputs().size() > 0));
+                System.out.println(" - !danglingMergeFrameState : " + (!danglingMergeFrameState(n)));*/
+                return exitFrameStates.isNotNewMarked(n)
+                || (inOrBefore.isNotNewNotMarked(n) && n.inputs().size() > 0 && !afterColoringFramestate(n)); //TODO (gd) hum
+            }
+            public boolean afterColoringFramestate(Node n) {
+                if (!(n instanceof FrameState)) {
+                    return false;
+                }
+                final FrameState frameState = (FrameState) n;
+                Merge block = frameState.block();
+                if (block != null) {
+                    return colors.get(block.next()) == null;
+                }
+                StateSplit stateSplit = frameState.stateSplit();
+                if (stateSplit != null) {
+                    return colors.get(stateSplit) == null;
+                }
+                for (FrameState inner : frameState.innerFrameStates()) {
+                    if (!afterColoringFramestate(inner)) {
+                        return false;
+                    }
+                }
+                return true;
+            }
+            @Override
+            public void fixNode(Node node, Node color) {
+                //System.out.println("fixNode(" + node + ", " + color + ")");
+                if (color == null) {
+                    // 'white' it out : make non-explorable
+                    if (!exitFrameStates.isNew(node)) {
+                        exitFrameStates.clear(node);
+                    }
+                    inOrBefore.mark(node);
+                } else {
+                    for (int i = 0; i < node.inputs().size(); i++) {
+                        Node input = node.inputs().get(i);
+                        if (input == null || newExitValues.isNew(input)) {
+                            continue;
+                        }
+                        NodeMap<Value> valueMap = newExitValues.get(input);
+                        if (valueMap != null) {
+                            Value replacement = getValueAt(color, valueMap, ((Value) input).kind);
+                            node.inputs().set(i, replacement);
+                        }
+                    }
+                }
+            }
+            @Override
+            public Value fixPhiInput(Value input, Node color) {
+                if (newExitValues.isNew(input)) {
+                    return input;
+                }
+                NodeMap<Value> valueMap = newExitValues.get(input);
+                if (valueMap != null) {
+                    return getValueAt(color, valueMap, input.kind);
+                }
+                return input;
+            }
+            @Override
+            public List<Node> parentColors(Node color) {
+                if (!(color instanceof Merge)) {
+                    return Collections.emptyList();
+                }
+                Merge merge = (Merge) color;
+                List<Node> parentColors = new ArrayList<Node>(merge.phiPredecessorCount());
+                for (Node pred : merge.phiPredecessors()) {
+                    parentColors.add(colors.get(pred));
+                }
+                return parentColors;
+            }
+            @Override
+            public Merge merge(Node color) {
+                return (Merge) color;
+            }
+        });
+
+        /*if (compilation.compiler.isObserved()) {
+            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After split from colors", graph, true, false));
+        }*/
+    }
+
+    private static PeelingResult preparePeeling(Loop loop, FixedNode from) {
+        LoopBegin loopBegin = loop.loopBegin();
+        Graph graph = loopBegin.graph();
+        NodeBitMap marked = computeLoopNodesFrom(loop, from);
+        GraalCompilation compilation = GraalCompilation.compilation();
+        /*if (compilation.compiler.isObserved()) {
+            Map<String, Object> debug = new HashMap<String, Object>();
+            debug.put("marked", marked);
+            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After computeLoopNodesFrom", loopBegin.graph(), true, false, debug));
+        }*/
+        if (from == loopBegin.loopEnd()) {
+            clearWithState(from, marked);
+        }
+        clearWithState(loopBegin, marked);
+        Map<Node, Node> replacements = new HashMap<Node, Node>();
+        NodeMap<Placeholder> phis = graph.createNodeMap();
+        NodeMap<StateSplit> exits = graph.createNodeMap();
+        NodeBitMap unaffectedExits = graph.createNodeBitMap();
+        NodeBitMap clonedExits = graph.createNodeBitMap();
+        NodeBitMap exitFrameStates = graph.createNodeBitMap();
+        for (Node exit : loop.exits()) {
+            if (marked.isMarked(exit.singlePredecessor())) {
+                StateSplit pExit = findNearestMergableExitPoint((FixedNode) exit, marked);
+                markWithState(pExit, marked);
+                clonedExits.mark(pExit);
+                FrameState stateAfter = pExit.stateAfter();
+                while (stateAfter != null) {
+                    exitFrameStates.mark(stateAfter);
+                    stateAfter = stateAfter.outerFrameState();
+                }
+            } else {
+                unaffectedExits.mark(exit);
+            }
+        }
+
+        NodeBitMap dataOut = graph.createNodeBitMap();
+        for (Node n : marked) {
+            if (!(n instanceof FrameState)) {
+                for (Node usage : n.dataUsages()) {
+                    if ((!marked.isMarked(usage) && !((usage instanceof Phi) && ((Phi) usage).merge() != loopBegin))
+                                    || (marked.isMarked(usage) && exitFrameStates.isMarked(usage))) {
+                        dataOut.mark(n);
+                        break;
+                    }
+                }
+            }
+        }
+
+        for (Node n : marked) {
+            if (n instanceof Phi && ((Phi) n).merge() == loopBegin) {
+                Placeholder p = new Placeholder(graph);
+                replacements.put(n, p);
+                phis.set(n, p);
+                marked.clear(n);
+            }
+            for (Node input : n.dataInputs()) {
+                if (!marked.isMarked(input) && (!(input instanceof Phi) || ((Phi) input).merge() != loopBegin) && replacements.get(input) == null) {
+                    replacements.put(input, input);
+                }
+            }
+        }
+
+        //GraalCompilation compilation = GraalCompilation.compilation();
+        if (compilation.compiler.isObserved()) {
+            Map<String, Object> debug = new HashMap<String, Object>();
+            debug.put("marked", marked);
+            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "Before addDuplicate loop#" + loopBegin.id(), loopBegin.graph(), true, false, debug));
+        }
+
+        Map<Node, Node> duplicates = graph.addDuplicate(marked, replacements);
+
+        /*System.out.println("Dup mapping :");
+        for (Entry<Node, Node> entry : duplicates.entrySet()) {
+            System.out.println(" - " + entry.getKey().id() + " -> " + entry.getValue().id());
+        }*/
+
+        NodeMap<Node> dataOutMapping = graph.createNodeMap();
+        for (Node n : dataOut) {
+            Node newOut = duplicates.get(n);
+            if (newOut == null) {
+                newOut = replacements.get(n);
+            }
+            assert newOut != null;
+            dataOutMapping.set(n, newOut);
+        }
+
+        for (Node n : clonedExits) {
+            exits.set(n, (StateSplit) duplicates.get(n));
+        }
+
+        NodeMap<Node> phiInits = graph.createNodeMap();
+        int backIndex = loopBegin.phiPredecessorIndex(loopBegin.loopEnd());
+        int fowardIndex = loopBegin.phiPredecessorIndex(loopBegin.forwardEdge());
+        for (Phi phi : loopBegin.phis()) {
+            Value backValue = phi.valueAt(backIndex);
+            if (marked.isMarked(backValue)) {
+                phiInits.set(phi, duplicates.get(backValue));
+            } else if (from == loopBegin.loopEnd()) {
+                if (backValue instanceof Phi && ((Phi) backValue).merge() == loopBegin) {
+                    Phi backPhi = (Phi) backValue;
+                    phiInits.set(phi, backPhi.valueAt(fowardIndex));
+                } else {
+                    phiInits.set(phi, backValue);
+                }
+            }
+        }
+
+        FixedNode newBegin = (FixedNode) duplicates.get(loopBegin.next());
+        FixedNode newFrom = (FixedNode) duplicates.get(from == loopBegin.loopEnd() ? from.singlePredecessor() : from);
+        return new PeelingResult(newBegin, newFrom, exits, phis, phiInits, dataOutMapping, unaffectedExits, exitFrameStates, marked);
+    }
+
+    private static StateSplit findNearestMergableExitPoint(FixedNode exit, NodeBitMap marked) {
+
+        LinkedList<FixedNode> branches = new LinkedList<FixedNode>();
+        branches.add(exit);
+        while (true) {
+            if (branches.size() == 1) {
+                final FixedNode fixedNode = branches.get(0);
+                if (fixedNode instanceof StateSplit && ((StateSplit) fixedNode).stateAfter() != null) {
+                    return (StateSplit) fixedNode;
+                }
+            } else {
+                // FixedNode current = branches.poll();
+                // TODO (gd) find appropriate point : will be useful if a loop exit goes "up" as a result of making a branch dead in the loop body
+            }
+        }
+    }
+
+    private static NodeBitMap inOrAfter(Loop loop) {
+        return inOrAfter(loop, loop.cfgNodes());
+    }
+
+    private static NodeBitMap inOrAfter(Loop loop, NodeBitMap cfgNodes) {
+        return inOrAfter(loop, cfgNodes, true);
+    }
+
+    private static NodeBitMap inOrAfter(Loop loop, NodeBitMap cfgNodes, boolean full) {
+        Graph graph = loop.loopBegin().graph();
+        NodeBitMap inOrAfter = graph.createNodeBitMap();
+        NodeFlood work = graph.createNodeFlood();
+        work.addAll(cfgNodes);
+        for (Node n : work) {
+            //inOrAfter.mark(n);
+            markWithState(n, inOrAfter);
+            if (full) {
+                for (Node sux : n.successors()) {
+                    if (sux != null) {
+                        work.add(sux);
+                    }
+                }
+            }
+            for (Node usage : n.usages()) {
+                if (usage instanceof Phi) { // filter out data graph cycles
+                    Phi phi = (Phi) usage;
+                    Merge merge = phi.merge();
+                    if (merge instanceof LoopBegin) {
+                        LoopBegin phiLoop = (LoopBegin) merge;
+                        int backIndex = phiLoop.phiPredecessorIndex(phiLoop.loopEnd());
+                        if (phi.valueAt(backIndex) == n) {
+                            continue;
+                        }
+                    }
+                }
+                work.add(usage);
+            }
+        }
+        return inOrAfter;
+    }
+
+    private static NodeBitMap inOrBefore(Loop loop) {
+        return inOrBefore(loop, inOrAfter(loop));
+    }
+
+    private static NodeBitMap inOrBefore(Loop loop, NodeBitMap inOrAfter) {
+        return inOrBefore(loop, inOrAfter, loop.cfgNodes());
+    }
+
+    private static NodeBitMap inOrBefore(Loop loop, NodeBitMap inOrAfter, NodeBitMap cfgNodes) {
+        return inOrBefore(loop, inOrAfter, cfgNodes, true);
+    }
+
+    private static NodeBitMap inOrBefore(Loop loop, NodeBitMap inOrAfter, NodeBitMap cfgNodes, boolean full) {
+        Graph graph = loop.loopBegin().graph();
+        NodeBitMap inOrBefore = graph.createNodeBitMap();
+        NodeFlood work = graph.createNodeFlood();
+        work.addAll(cfgNodes);
+        for (Node n : work) {
+            inOrBefore.mark(n);
+            if (full) {
+                for (Node pred : n.predecessors()) {
+                    work.add(pred);
+                }
+            }
+            if (n instanceof Phi) { // filter out data graph cycles
+                Phi phi = (Phi) n;
+                if (phi.type() == PhiType.Value) {
+                    int backIndex = -1;
+                    Merge merge = phi.merge();
+                    if (merge instanceof LoopBegin && cfgNodes.isNotNewNotMarked(((LoopBegin) merge).loopEnd())) {
+                        LoopBegin phiLoop = (LoopBegin) merge;
+                        backIndex = phiLoop.phiPredecessorIndex(phiLoop.loopEnd());
+                    }
+                    for (int i = 0; i < phi.valueCount(); i++) {
+                        if (i != backIndex) {
+                            work.add(phi.valueAt(i));
+                        }
+                    }
+                }
+            } else {
+                for (Node in : n.inputs()) {
+                    if (in != null) {
+                        work.add(in);
+                    }
+                }
+                if (full) {
+                    for (Node sux : n.cfgSuccessors()) { // go down into branches that are not 'inOfAfter'
+                        if (sux != null && !inOrAfter.isMarked(sux)) {
+                            work.add(sux);
+                        }
+                    }
+                    if (n instanceof LoopBegin && n != loop.loopBegin()) {
+                        Loop p = loop.parent;
+                        boolean isParent = false;
+                        while (p != null) {
+                            if (p.loopBegin() == n) {
+                                isParent = true;
+                                break;
+                            }
+                            p = p.parent;
+                        }
+                        if (!isParent) {
+                            work.add(((LoopBegin) n).loopEnd());
+                        }
+                    }
+                }
+                if (cfgNodes.isNotNewMarked(n)) { //add all values from the exits framestates
+                    for (Node sux : n.cfgSuccessors()) {
+                        if (loop.exits().isNotNewMarked(sux) && sux instanceof StateSplit) {
+                            FrameState stateAfter = ((StateSplit) sux).stateAfter();
+                            while (stateAfter != null) {
+                                for (Node in : stateAfter.inputs()) {
+                                    if (!(in instanceof FrameState)) {
+                                        work.add(in);
+                                    }
+                                }
+                                stateAfter = stateAfter.outerFrameState();
+                            }
+                        }
+                    }
+                }
+                if (n instanceof Merge) { //add phis & counters
+                    for (Node usage : n.dataUsages()) {
+                        if (!(usage instanceof LoopEnd)) {
+                            work.add(usage);
+                        }
+                    }
+                }
+                if (n instanceof AbstractVectorNode) {
+                    for (Node usage : n.usages()) {
+                        work.add(usage);
+                    }
+                }
+            }
+        }
+        return inOrBefore;
+    }
+
+    private static void markWithState(Node n, NodeBitMap map) {
+        map.mark(n);
+        if (n instanceof StateSplit) {
+            FrameState stateAfter = ((StateSplit) n).stateAfter();
+            while (stateAfter != null) {
+                map.mark(stateAfter);
+                stateAfter = stateAfter.outerFrameState();
+            }
+        }
+    }
+
+    private static void clearWithState(Node n, NodeBitMap map) {
+        map.clear(n);
+        if (n instanceof StateSplit) {
+            FrameState stateAfter = ((StateSplit) n).stateAfter();
+            while (stateAfter != null) {
+                map.clear(stateAfter);
+                stateAfter = stateAfter.outerFrameState();
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/Util.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,439 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.util;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code Util} class contains a motley collection of utility methods used throughout the compiler.
+ *
+ * @author Ben L. Titzer
+ * @author Doug Simon
+ */
+public class Util {
+
+    public static final int PRINTING_LINE_WIDTH = 40;
+    public static final char SECTION_CHARACTER = '*';
+    public static final char SUB_SECTION_CHARACTER = '=';
+    public static final char SEPERATOR_CHARACTER = '-';
+
+    public static RuntimeException unimplemented() {
+        throw new InternalError("unimplemented");
+    }
+
+    public static RuntimeException unimplemented(String msg) {
+        throw new InternalError("unimplemented:" + msg);
+    }
+
+    public static RuntimeException shouldNotReachHere() {
+        throw new InternalError("should not reach here");
+    }
+
+    public static RuntimeException shouldNotReachHere(String msg) {
+        throw new InternalError("Should not reach here: " + msg);
+    }
+
+    public static <T> boolean replaceInList(T a, T b, List<T> list) {
+        final int max = list.size();
+        for (int i = 0; i < max; i++) {
+            if (list.get(i) == a) {
+                list.set(i, b);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static <T> boolean replaceAllInList(T a, T b, List<T> list) {
+        final int max = list.size();
+        for (int i = 0; i < max; i++) {
+            if (list.get(i) == a) {
+                list.set(i, b);
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Statically cast an object to an arbitrary Object type. Dynamically checked.
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T uncheckedCast(Class<T> type, Object object) {
+        return (T) object;
+    }
+
+    /**
+     * Statically cast an object to an arbitrary Object type. Dynamically checked.
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T uncheckedCast(Object object) {
+        return (T) object;
+    }
+
+    /**
+     * Utility method to combine a base hash with the identity hash of one or more objects.
+     *
+     * @param hash the base hash
+     * @param x the object to add to the hash
+     * @return the combined hash
+     */
+    public static int hash1(int hash, Object x) {
+        // always set at least one bit in case the hash wraps to zero
+        return 0x10000000 | (hash + 7 * System.identityHashCode(x));
+    }
+
+    /**
+     * Utility method to combine a base hash with the identity hash of one or more objects.
+     *
+     * @param hash the base hash
+     * @param x the first object to add to the hash
+     * @param y the second object to add to the hash
+     * @return the combined hash
+     */
+    public static int hash2(int hash, Object x, Object y) {
+        // always set at least one bit in case the hash wraps to zero
+        return 0x20000000 | (hash + 7 * System.identityHashCode(x) + 11 * System.identityHashCode(y));
+    }
+
+    /**
+     * Utility method to combine a base hash with the identity hash of one or more objects.
+     *
+     * @param hash the base hash
+     * @param x the first object to add to the hash
+     * @param y the second object to add to the hash
+     * @param z the third object to add to the hash
+     * @return the combined hash
+     */
+    public static int hash3(int hash, Object x, Object y, Object z) {
+        // always set at least one bit in case the hash wraps to zero
+        return 0x30000000 | (hash + 7 * System.identityHashCode(x) + 11 * System.identityHashCode(y) + 13 * System.identityHashCode(z));
+    }
+
+    /**
+     * Utility method to combine a base hash with the identity hash of one or more objects.
+     *
+     * @param hash the base hash
+     * @param x the first object to add to the hash
+     * @param y the second object to add to the hash
+     * @param z the third object to add to the hash
+     * @param w the fourth object to add to the hash
+     * @return the combined hash
+     */
+    public static int hash4(int hash, Object x, Object y, Object z, Object w) {
+        // always set at least one bit in case the hash wraps to zero
+        return 0x40000000 | (hash + 7 * System.identityHashCode(x) + 11 * System.identityHashCode(y) + 13 * System.identityHashCode(z) + 17 * System.identityHashCode(w));
+    }
+
+    static {
+        assert CiUtil.log2(2) == 1;
+        assert CiUtil.log2(4) == 2;
+        assert CiUtil.log2(8) == 3;
+        assert CiUtil.log2(16) == 4;
+        assert CiUtil.log2(32) == 5;
+        assert CiUtil.log2(0x40000000) == 30;
+
+        assert CiUtil.log2(2L) == 1;
+        assert CiUtil.log2(4L) == 2;
+        assert CiUtil.log2(8L) == 3;
+        assert CiUtil.log2(16L) == 4;
+        assert CiUtil.log2(32L) == 5;
+        assert CiUtil.log2(0x4000000000000000L) == 62;
+
+        assert !CiUtil.isPowerOf2(3);
+        assert !CiUtil.isPowerOf2(5);
+        assert !CiUtil.isPowerOf2(7);
+        assert !CiUtil.isPowerOf2(-1);
+
+        assert CiUtil.isPowerOf2(2);
+        assert CiUtil.isPowerOf2(4);
+        assert CiUtil.isPowerOf2(8);
+        assert CiUtil.isPowerOf2(16);
+        assert CiUtil.isPowerOf2(32);
+        assert CiUtil.isPowerOf2(64);
+    }
+
+    /**
+     * Sets the element at a given position of a list and ensures that this position exists. If the list is current
+     * shorter than the position, intermediate positions are filled with a given value.
+     *
+     * @param list the list to put the element into
+     * @param pos the position at which to insert the element
+     * @param x the element that should be inserted
+     * @param filler the filler element that is used for the intermediate positions in case the list is shorter than pos
+     */
+    public static <T> void atPutGrow(List<T> list, int pos, T x, T filler) {
+        if (list.size() < pos + 1) {
+            while (list.size() < pos + 1) {
+                list.add(filler);
+            }
+            assert list.size() == pos + 1;
+        }
+
+        assert list.size() >= pos + 1;
+        list.set(pos, x);
+    }
+
+    public static void breakpoint() {
+        // do nothing.
+    }
+
+    public static void guarantee(boolean b, String string) {
+        if (!b) {
+            throw new CiBailout(string);
+        }
+    }
+
+    public static void warning(String string) {
+        TTY.println("WARNING: " + string);
+    }
+
+    public static int safeToInt(long l) {
+        assert (int) l == l;
+        return (int) l;
+    }
+
+    public static int roundUp(int number, int mod) {
+        return ((number + mod - 1) / mod) * mod;
+    }
+
+    public static void truncate(List<?> list, int length) {
+        while (list.size() > length) {
+            list.remove(list.size() - 1);
+        }
+    }
+
+    public static void printSection(String name, char sectionCharacter) {
+
+        String header = " " + name + " ";
+        int remainingCharacters = PRINTING_LINE_WIDTH - header.length();
+        int leftPart = remainingCharacters / 2;
+        int rightPart = remainingCharacters - leftPart;
+        for (int i = 0; i < leftPart; i++) {
+            TTY.print(sectionCharacter);
+        }
+
+        TTY.print(header);
+
+        for (int i = 0; i < rightPart; i++) {
+            TTY.print(sectionCharacter);
+        }
+
+        TTY.println();
+    }
+
+    /**
+     * Prints entries in a byte array as space separated hex values to {@link TTY}.
+     *
+     * @param address an address at which the bytes are located. This is used to print an address prefix per line of output.
+     * @param array the array containing all the bytes to print
+     * @param bytesPerLine the number of values to print per line of output
+     */
+    public static void printBytes(long address, byte[] array, int bytesPerLine) {
+        printBytes(address, array, 0, array.length, bytesPerLine);
+    }
+
+    /**
+     * Prints entries in a byte array as space separated hex values to {@link TTY}.
+     *
+     * @param address an address at which the bytes are located. This is used to print an address prefix per line of output.
+     * @param array the array containing the bytes to print
+     * @param offset the offset in {@code array} of the values to print
+     * @param length the number of values from {@code array} print
+     * @param bytesPerLine the number of values to print per line of output
+     */
+    public static void printBytes(long address, byte[] array, int offset, int length, int bytesPerLine) {
+        assert bytesPerLine > 0;
+        boolean newLine = true;
+        for (int i = 0; i < length; i++) {
+            if (newLine) {
+                TTY.print("%08x: ", address + i);
+                newLine = false;
+            }
+            TTY.print("%02x ", array[i]);
+            if (i % bytesPerLine == bytesPerLine - 1) {
+                TTY.println();
+                newLine = true;
+            }
+        }
+
+        if (length % bytesPerLine != bytesPerLine) {
+            TTY.println();
+        }
+    }
+
+    public static CiKind[] signatureToKinds(RiSignature signature, CiKind receiverKind) {
+        int args = signature.argumentCount(false);
+        CiKind[] result;
+        int i = 0;
+        if (receiverKind != null) {
+            result = new CiKind[args + 1];
+            result[0] = receiverKind;
+            i = 1;
+        } else {
+            result = new CiKind[args];
+        }
+        for (int j = 0; j < args; j++) {
+            result[i + j] = signature.argumentKindAt(j);
+        }
+        return result;
+    }
+
+    public static boolean isShiftCount(int x) {
+        return 0 <= x && x < 32;
+    }
+
+    /**
+     * Determines if a given {@code int} value is the range of unsigned byte values.
+     */
+    public static boolean isUByte(int x) {
+        return (x & 0xff) == x;
+    }
+
+    /**
+     * Determines if a given {@code int} value is the range of signed byte values.
+     */
+    public static boolean isByte(int x) {
+        return (byte) x == x;
+    }
+
+    /**
+     * Determines if a given {@code long} value is the range of unsigned byte values.
+     */
+    public static boolean isUByte(long x) {
+        return (x & 0xffL) == x;
+    }
+
+    /**
+     * Determines if a given {@code long} value is the range of signed byte values.
+     */
+    public static boolean isByte(long l) {
+        return (byte) l == l;
+    }
+
+    /**
+     * Determines if a given {@code long} value is the range of unsigned int values.
+     */
+    public static boolean isUInt(long x) {
+        return (x & 0xffffffffL) == x;
+    }
+
+    /**
+     * Determines if a given {@code long} value is the range of signed int values.
+     */
+    public static boolean isInt(long l) {
+        return (int) l == l;
+    }
+    /**
+     * Determines if a given {@code int} value is the range of signed short values.
+     */
+    public static boolean isShort(int x) {
+        return (short) x == x;
+    }
+
+    public static boolean is32bit(long x) {
+        return -0x80000000L <= x && x < 0x80000000L;
+    }
+
+    public static short safeToShort(int v) {
+        assert isShort(v);
+        return (short) v;
+    }
+
+    /**
+     * Determines if the kinds of two given IR nodes are equal at the {@linkplain #archKind(CiKind) architecture}
+     * level in the context of the {@linkplain GraalCompilation#compilation()} compilation.
+     */
+    public static boolean archKindsEqual(Value i, Value other) {
+        return archKindsEqual(i.kind, other.kind);
+    }
+
+    /**
+     * Determines if two given kinds are equal at the {@linkplain #archKind(CiKind) architecture} level
+     * in the context of the {@linkplain GraalCompilation#compilation()} compilation.
+     */
+    public static boolean archKindsEqual(CiKind k1, CiKind k2) {
+        GraalCompilation compilation = GraalCompilation.compilation();
+        assert compilation != null : "missing compilation context";
+        return compilation.archKindsEqual(k1, k2);
+    }
+
+    /**
+     * Translates a given kind to a {@linkplain GraalCompilation#archKind(CiKind) canonical architecture}
+     * kind in the context of the {@linkplain GraalCompilation#compilation() current} compilation.
+     */
+    public static CiKind archKind(CiKind kind) {
+        GraalCompilation compilation = GraalCompilation.compilation();
+        assert compilation != null : "missing compilation context";
+        return compilation.archKind(kind);
+    }
+
+
+    /**
+     * Checks that two instructions are equivalent, optionally comparing constants.
+     * @param x the first instruction
+     * @param y the second instruction
+     * @param compareConstants {@code true} if equivalent constants should be considered equivalent
+     * @return {@code true} if the instructions are equivalent; {@code false} otherwise
+     */
+    public static boolean equivalent(FixedNodeWithNext x, FixedNodeWithNext y, boolean compareConstants) {
+        if (x == y) {
+            return true;
+        }
+        if (compareConstants && x != null && y != null) {
+            if (x.isConstant() && x.asConstant().equivalent(y.asConstant())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Converts a given instruction to a value string. The representation of an instruction as
+     * a value is formed by concatenating the {@linkplain com.sun.cri.ci.CiKind#typeChar character} denoting its
+     * {@linkplain Value#kind kind} and its {@linkplain Value#id()}. For example, {@code "i13"}.
+     *
+     * @param value the instruction to convert to a value string. If {@code value == null}, then "-" is returned.
+     * @return the instruction representation as a string
+     */
+    public static String valueString(Value value) {
+        return (value == null) ? "-" : ("" + value.kind.typeChar + value.id());
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T extends Node> Collection<T> filter(Collection<Node> nodes, Class<T> clazz) {
+        ArrayList<T> phis = new ArrayList<T>();
+        for (Node node : nodes) {
+            if (clazz.isInstance(node)) {
+                phis.add((T) node);
+            }
+        }
+        return phis;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,705 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.value;
+
+import static com.oracle.max.graal.compiler.value.ValueUtil.*;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.ir.Phi.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code FrameState} class encapsulates the frame state (i.e. local variables and
+ * operand stack) at a particular point in the abstract interpretation.
+ */
+public final class FrameState extends Value implements FrameStateAccess {
+
+    private static final int INPUT_COUNT = 1;
+
+    private static final int INPUT_OUTER_FRAME_STATE = 0;
+
+    protected final int localsSize;
+
+    protected final int stackSize;
+
+    protected final int locksSize;
+
+    private boolean rethrowException;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    public static final int BEFORE_BCI = -2;
+    public static final int AFTER_BCI = -3;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + localsSize + stackSize + locksSize;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    public FrameState outerFrameState() {
+        return (FrameState) inputs().get(super.inputCount() + INPUT_OUTER_FRAME_STATE);
+    }
+
+    public FrameState setOuterFrameState(FrameState n) {
+        return (FrameState) inputs().set(super.inputCount() + INPUT_OUTER_FRAME_STATE, n);
+    }
+
+    @Override
+    public void setValueAt(int i, Value x) {
+        inputs().set(INPUT_COUNT + i, x);
+    }
+
+    /**
+     * The bytecode index to which this frame state applies. This will be {@code -1}
+     * iff this state is mutable.
+     */
+    public final int bci;
+
+    public final RiMethod method;
+
+    /**
+     * Creates a {@code FrameState} for the given scope and maximum number of stack and local variables.
+     *
+     * @param bci the bytecode index of the frame state
+     * @param localsSize number of locals
+     * @param stackSize size of the stack
+     * @param lockSize number of locks
+     */
+    public FrameState(RiMethod method, int bci, int localsSize, int stackSize, int locksSize, boolean rethrowException, Graph graph) {
+        super(CiKind.Illegal, localsSize + stackSize + locksSize + INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.method = method;
+        this.bci = bci;
+        this.localsSize = localsSize;
+        this.stackSize = stackSize;
+        this.locksSize = locksSize;
+        this.rethrowException = rethrowException;
+        GraalMetrics.FrameStatesCreated++;
+        GraalMetrics.FrameStateValuesCreated += localsSize + stackSize + locksSize;
+    }
+
+    FrameState(RiMethod method, int bci, Value[] locals, Value[] stack, int stackSize, ArrayList<Value> locks, boolean rethrowException, Graph graph) {
+        this(method, bci, locals.length, stackSize, locks.size(), rethrowException, graph);
+        for (int i = 0; i < locals.length; i++) {
+            setValueAt(i, locals[i]);
+        }
+        for (int i = 0; i < stackSize; i++) {
+            setValueAt(localsSize + i, stack[i]);
+        }
+        for (int i = 0; i < locks.size(); i++) {
+            setValueAt(locals.length + stackSize + i, locks.get(i));
+        }
+    }
+
+    public boolean rethrowException() {
+        return rethrowException;
+    }
+
+    public RiMethod method() {
+        return method;
+    }
+
+    public void addVirtualObjectMapping(Node virtualObject) {
+        assert virtualObject instanceof VirtualObjectField || virtualObject instanceof Phi : virtualObject;
+        variableInputs().add(virtualObject);
+    }
+
+    public int virtualObjectMappingCount() {
+        return variableInputs().size();
+    }
+
+    public Node virtualObjectMappingAt(int i) {
+        return variableInputs().get(i);
+    }
+
+    public List<Node> virtualObjectMappings() {
+        return variableInputs();
+    }
+
+    /**
+     * Gets a copy of this frame state.
+     */
+    public FrameState duplicate(int bci) {
+        return duplicate(bci, false);
+    }
+
+    public FrameState duplicate(int bci, boolean duplicateOuter) {
+        FrameState other = new FrameState(method, bci, localsSize, stackSize, locksSize, rethrowException, graph());
+        other.inputs().setAll(inputs());
+        other.variableInputs().addAll(variableInputs());
+        FrameState outerFrameState = outerFrameState();
+        if (duplicateOuter && outerFrameState != null) {
+            outerFrameState = outerFrameState.duplicate(outerFrameState.bci, duplicateOuter);
+        }
+        other.setOuterFrameState(outerFrameState);
+        return other;
+    }
+
+    @Override
+    public FrameState duplicateWithException(int bci, Value exceptionObject) {
+        return duplicateModified(bci, true, CiKind.Void, exceptionObject);
+    }
+
+    /**
+     * 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 are expected to be in slot encoding: a long
+     * or double is followed by a null slot.
+     */
+    public FrameState duplicateModified(int bci, boolean rethrowException, CiKind popKind, Value... pushedValues) {
+        int popSlots = popKind.sizeInSlots();
+        int pushSlots = pushedValues.length;
+        FrameState other = new FrameState(method, bci, localsSize, stackSize - popSlots + pushSlots, locksSize(), rethrowException, graph());
+        for (int i = 0; i < localsSize; i++) {
+            other.setValueAt(i, localAt(i));
+        }
+        for (int i = 0; i < stackSize - popSlots; i++) {
+            other.setValueAt(localsSize + i, stackAt(i));
+        }
+        int slot = localsSize + stackSize - popSlots;
+        for (int i = 0; i < pushSlots; i++) {
+            other.setValueAt(slot++, pushedValues[i]);
+        }
+        for (int i = 0; i < locksSize; i++) {
+            other.setValueAt(localsSize + other.stackSize + i, lockAt(i));
+        }
+        other.variableInputs().addAll(variableInputs());
+        other.setOuterFrameState(outerFrameState());
+        return other;
+    }
+
+    public boolean isCompatibleWith(FrameStateAccess other) {
+        if (stackSize() != other.stackSize() || localsSize() != other.localsSize() || locksSize() != other.locksSize()) {
+            return false;
+        }
+        for (int i = 0; i < stackSize(); i++) {
+            Value x = stackAt(i);
+            Value y = other.stackAt(i);
+            if (x != y && typeMismatch(x, y)) {
+                return false;
+            }
+        }
+        for (int i = 0; i < locksSize(); i++) {
+            if (lockAt(i) != other.lockAt(i)) {
+                return false;
+            }
+        }
+        if (other.outerFrameState() != outerFrameState()) {
+            return false;
+        }
+        return true;
+    }
+
+    public boolean equals(FrameStateAccess other) {
+        if (stackSize() != other.stackSize() || localsSize() != other.localsSize() || locksSize() != other.locksSize()) {
+            return false;
+        }
+        for (int i = 0; i < stackSize(); i++) {
+            Value x = stackAt(i);
+            Value y = other.stackAt(i);
+            if (x != y) {
+                return false;
+            }
+        }
+        for (int i = 0; i < locksSize(); i++) {
+            if (lockAt(i) != other.lockAt(i)) {
+                return false;
+            }
+        }
+        if (other.outerFrameState() != outerFrameState()) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Gets the size of the local variables.
+     */
+    public int localsSize() {
+        return localsSize;
+    }
+
+    /**
+     * Gets the current size (height) of the stack.
+     */
+    public int stackSize() {
+        return stackSize;
+    }
+
+    /**
+     * Gets number of locks held by this frame state.
+     */
+    public int locksSize() {
+        return locksSize;
+    }
+
+    /**
+     * Invalidates the local variable at the specified index. If the specified index refers to a doubleword local, then
+     * invalidates the high word as well.
+     *
+     * @param i the index of the local to invalidate
+     */
+    public void invalidateLocal(int i) {
+        // note that for double word locals, the high slot should already be null
+        // unless the local is actually dead and the high slot is being reused;
+        // in either case, it is not necessary to null the high slot
+        setValueAt(i, null);
+    }
+
+    /**
+     * Stores a given local variable at the specified index. If the value is a {@linkplain CiKind#isDoubleWord() double word},
+     * then the next local variable index is also overwritten.
+     *
+     * @param i the index at which to store
+     * @param x the instruction which produces the value for the local
+     */
+    public void storeLocal(int i, Value x) {
+        assert i < localsSize : "local variable index out of range: " + i;
+        invalidateLocal(i);
+        setValueAt(i, x);
+        if (isDoubleWord(x)) {
+            // (tw) if this was a double word then kill i+1
+            setValueAt(i + 1, null);
+        }
+        if (i > 0) {
+            // if there was a double word at i - 1, then kill it
+            Value p = localAt(i - 1);
+            if (isDoubleWord(p)) {
+                setValueAt(i - 1, null);
+            }
+        }
+    }
+
+    /**
+     * Gets the value in the local variables at the specified index.
+     *
+     * @param i the index into the locals
+     * @return the instruction that produced the value for the specified local
+     */
+    public Value localAt(int i) {
+        assert i < localsSize : "local variable index out of range: " + i;
+        return valueAt(i);
+    }
+
+    /**
+     * Get the value on the stack at the specified stack index.
+     *
+     * @param i the index into the stack, with {@code 0} being the bottom of the stack
+     * @return the instruction at the specified position in the stack
+     */
+    public Value stackAt(int i) {
+        assert i >= 0 && i < (localsSize + stackSize);
+        return valueAt(localsSize + i);
+    }
+
+    /**
+     * Retrieves the lock at the specified index in the lock stack.
+     * @param i the index into the lock stack
+     * @return the instruction which produced the object at the specified location in the lock stack
+     */
+    public Value lockAt(int i) {
+        assert i >= 0;
+        return valueAt(localsSize + stackSize + i);
+    }
+
+    /**
+     * Inserts a phi statement into the stack at the specified stack index.
+     * @param block the block begin for which we are creating the phi
+     * @param i the index into the stack for which to create a phi
+     */
+    public Phi setupPhiForStack(Merge block, int i) {
+        Value p = stackAt(i);
+        if (p != null) {
+            if (p instanceof Phi) {
+                Phi phi = (Phi) p;
+                if (phi.merge() == block) {
+                    return phi;
+                }
+            }
+            Phi phi = new Phi(p.kind, block, PhiType.Value, graph());
+            setValueAt(localsSize + i, phi);
+            return phi;
+        }
+        return null;
+    }
+
+    /**
+     * Inserts a phi statement for the local at the specified index.
+     * @param block the block begin for which we are creating the phi
+     * @param i the index of the local variable for which to create the phi
+     */
+    public Phi setupPhiForLocal(Merge block, int i) {
+        Value p = localAt(i);
+        if (p instanceof Phi) {
+            Phi phi = (Phi) p;
+            if (phi.merge() == block) {
+                return phi;
+            }
+        }
+        Phi phi = new Phi(p.kind, block, PhiType.Value, graph());
+        storeLocal(i, phi);
+        return phi;
+    }
+
+    /**
+     * Gets the value at a specified index in the set of operand stack and local values represented by this frame.
+     * This method should only be used to iterate over all the values in this frame, irrespective of whether
+     * they are on the stack or in local variables.
+     * To iterate the stack slots, the {@link #stackAt(int)} and {@link #stackSize()} methods should be used.
+     * To iterate the local variables, the {@link #localAt(int)} and {@link #localsSize()} methods should be used.
+     *
+     * @param i a value in the range {@code [0 .. valuesSize()]}
+     * @return the value at index {@code i} which may be {@code null}
+     */
+    public Value valueAt(int i) {
+        assert i < (localsSize + stackSize + locksSize);
+        return (Value) inputs().get(INPUT_COUNT + i);
+    }
+
+    /**
+     * The number of operand stack slots and local variables in this frame.
+     * This method should typically only be used in conjunction with {@link #valueAt(int)}.
+     * To iterate the stack slots, the {@link #stackAt(int)} and {@link #stackSize()} methods should be used.
+     * To iterate the local variables, the {@link #localAt(int)} and {@link #localsSize()} methods should be used.
+     *
+     * @return the number of local variables in this frame
+     */
+    public int valuesSize() {
+        return localsSize + stackSize;
+    }
+
+    private void checkSize(FrameStateAccess other) {
+        if (other.stackSize() != stackSize()) {
+            throw new CiBailout("stack sizes do not match");
+        } else if (other.localsSize() != localsSize) {
+            throw new CiBailout("local sizes do not match");
+        }
+    }
+
+    public void merge(Merge block, FrameStateAccess other) {
+        checkSize(other);
+        for (int i = 0; i < valuesSize(); i++) {
+            Value x = valueAt(i);
+            if (x != null) {
+                Value y = other.valueAt(i);
+                if (x != y || ((x instanceof Phi) && ((Phi) x).merge() == block)) {
+                    if (typeMismatch(x, y)) {
+                        if ((x instanceof Phi) && ((Phi) x).merge() == block) {
+                            x.replaceAtUsages(null);
+                            x.delete();
+                        }
+                        setValueAt(i, null);
+                        continue;
+                    }
+                    Phi phi = null;
+                    if (i < localsSize) {
+                        // this a local
+                        phi = setupPhiForLocal(block, i);
+                    } else {
+                        // this is a stack slot
+                        phi = setupPhiForStack(block, i - localsSize);
+                    }
+
+                    if (phi.valueCount() == 0) {
+                        int size = block.phiPredecessorCount();
+                        for (int j = 0; j < size; ++j) {
+                            phi.addInput(x);
+                        }
+                        phi.addInput((x == y) ? phi : y);
+                    } else {
+                        phi.addInput((x == y) ? phi : y);
+                    }
+
+                    assert phi.valueCount() == block.phiPredecessorCount() + (block instanceof LoopBegin ? 0 : 1) : "valueCount=" + phi.valueCount() + " predSize= " + block.phiPredecessorCount();
+               }
+            }
+        }
+    }
+
+    public Merge block() {
+        for (Node n : usages()) {
+            if (n instanceof Merge) {
+                return (Merge) n;
+            }
+        }
+        return null;
+    }
+
+    public StateSplit stateSplit() {
+        for (Node n : usages()) {
+            if (n instanceof StateSplit) {
+                return (StateSplit) n;
+            }
+        }
+        return null;
+    }
+
+    public Iterable<FrameState> innerFrameStates() {
+        final Iterator<Node> iterator = usages().iterator();
+        return new Iterable<FrameState>() {
+            @Override
+            public Iterator<FrameState> iterator() {
+                return new Iterator<FrameState>() {
+                    private Node next;
+                    @Override
+                    public void remove() {
+                        throw new UnsupportedOperationException();
+                    }
+                    @Override
+                    public FrameState next() {
+                        forward();
+                        if (!hasNext()) {
+                            throw new NoSuchElementException();
+                        }
+                        FrameState res = (FrameState) next;
+                        next = null;
+                        return res;
+                    }
+                    @Override
+                    public boolean hasNext() {
+                        forward();
+                        return next != null;
+                    }
+                    private void forward() {
+                        while (!(next instanceof FrameState) && iterator.hasNext()) {
+                            next = iterator.next();
+                        }
+                    }
+                };
+            }
+        };
+    }
+
+    /**
+     * The interface implemented by a client of {@link FrameState#forEachPhi(Merge, PhiProcedure)} and
+     * {@link FrameState#forEachLivePhi(Merge, PhiProcedure)}.
+     */
+    public static interface PhiProcedure {
+        boolean doPhi(Phi phi);
+    }
+
+    /**
+     * Checks whether this frame state has any {@linkplain Phi phi} statements.
+     */
+    public boolean hasPhis() {
+        for (int i = 0; i < valuesSize(); i++) {
+            Value value = valueAt(i);
+            if (value instanceof Phi) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * The interface implemented by a client of {@link FrameState#forEachLiveStateValue(ValueProcedure)}.
+     */
+    public static interface ValueProcedure {
+        void doValue(Value value);
+    }
+
+    /**
+     * Traverses all {@linkplain Value#isLive() live values} of this frame state.
+     *
+     * @param proc the call back called to process each live value traversed
+     */
+    public void forEachLiveStateValue(ValueProcedure proc) {
+        HashSet<VirtualObject> vobjs = null;
+        FrameState current = this;
+        do {
+            for (int i = 0; i < current.valuesSize(); i++) {
+                Value value = current.valueAt(i);
+                if (value instanceof VirtualObject) {
+                    if (vobjs == null) {
+                        vobjs = new HashSet<VirtualObject>();
+                    }
+                    vobjs.add((VirtualObject) value);
+                } else if (value != null) {
+                    proc.doValue(value);
+                }
+            }
+            current = current.outerFrameState();
+        } while (current != null);
+
+        if (vobjs != null) {
+            // collect all VirtualObjectField instances:
+            HashMap<VirtualObject, VirtualObjectField> objectStates = new HashMap<VirtualObject, VirtualObjectField>();
+            current = this;
+            do {
+                for (int i = 0; i < current.virtualObjectMappingCount(); i++) {
+                    VirtualObjectField field = (VirtualObjectField) current.virtualObjectMappingAt(i);
+                    // null states occur for objects with 0 fields
+                    if (field != null && !objectStates.containsKey(field.object())) {
+                        objectStates.put(field.object(), field);
+                    }
+                }
+                current = current.outerFrameState();
+            } while (current != null);
+
+            do {
+                HashSet<VirtualObject> vobjsCopy = new HashSet<VirtualObject>(vobjs);
+                for (VirtualObject vobj : vobjsCopy) {
+                    if (vobj.fields().length > 0) {
+                        boolean[] fieldState = new boolean[vobj.fields().length];
+                        FloatingNode currentField = objectStates.get(vobj);
+                        assert currentField != null : this;
+                        do {
+                            if (currentField instanceof VirtualObjectField) {
+                                int index = ((VirtualObjectField) currentField).index();
+                                Value value = ((VirtualObjectField) currentField).input();
+                                if (!fieldState[index]) {
+                                    fieldState[index] = true;
+                                    if (value instanceof VirtualObject) {
+                                        vobjs.add((VirtualObject) value);
+                                    } else {
+                                        proc.doValue(value);
+                                    }
+                                }
+                                currentField = ((VirtualObjectField) currentField).lastState();
+                            } else {
+                                assert currentField instanceof Phi : currentField;
+                                currentField = (FloatingNode) ((Phi) currentField).valueAt(0);
+                            }
+                        } while (currentField != null);
+                    }
+                    vobjs.remove(vobj);
+                }
+            } while (!vobjs.isEmpty());
+            if (!vobjs.isEmpty()) {
+                for (VirtualObject obj : vobjs) {
+                    TTY.println("+" + obj);
+                }
+                for (Node vobj : variableInputs()) {
+                    if (vobj instanceof VirtualObjectField) {
+                        TTY.println("-" + ((VirtualObjectField) vobj).object());
+                    } else {
+                        TTY.println("-" + vobj);
+                    }
+                }
+                for (Node n : this.usages()) {
+                    TTY.println("usage: " + n);
+                }
+            }
+            assert vobjs.isEmpty() : "at FrameState " + this;
+        }
+    }
+
+    @Override
+    public String toString() {
+        return super.toString();
+    }
+
+    public String toDetailedString() {
+        StringBuilder sb = new StringBuilder();
+        String nl = String.format("%n");
+        sb.append("[bci: ").append(bci).append("]");
+        if (rethrowException()) {
+            sb.append(" rethrows Exception");
+        }
+        sb.append(nl);
+        for (int i = 0; i < localsSize(); ++i) {
+            Value value = localAt(i);
+            sb.append(String.format("  local[%d] = %-8s : %s%n", i, value == null ? "bogus" : value.kind.javaName, value));
+        }
+        for (int i = 0; i < stackSize(); ++i) {
+            Value value = stackAt(i);
+            sb.append(String.format("  stack[%d] = %-8s : %s%n", i, value == null ? "bogus" : value.kind.javaName, value));
+        }
+        for (int i = 0; i < locksSize(); ++i) {
+            Value value = lockAt(i);
+            sb.append(String.format("  lock[%d] = %-8s : %s%n", i, value == null ? "bogus" : value.kind.javaName, value));
+        }
+        return sb.toString();
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitFrameState(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("FrameState");
+    }
+
+    @Override
+    public String shortName() {
+        return "FrameState@" + bci;
+    }
+
+    public void visitFrameState(FrameState i) {
+        // nothing to do for now
+    }
+
+    @Override
+    public Map<Object, Object> getDebugProperties() {
+        Map<Object, Object> properties = super.getDebugProperties();
+        properties.put("bci", bci);
+        properties.put("method", CiUtil.format("%H.%n(%p):%r", method, false));
+        StringBuilder str = new StringBuilder();
+        for (int i = 0; i < localsSize(); i++) {
+            str.append(i == 0 ? "" : ", ").append(localAt(i) == null ? "_" : localAt(i).id());
+        }
+        properties.put("locals", str.toString());
+        str = new StringBuilder();
+        for (int i = 0; i < stackSize(); i++) {
+            str.append(i == 0 ? "" : ", ").append(stackAt(i) == null ? "_" : stackAt(i).id());
+        }
+        properties.put("stack", str.toString());
+        str = new StringBuilder();
+        for (int i = 0; i < locksSize(); i++) {
+            str.append(i == 0 ? "" : ", ").append(lockAt(i) == null ? "_" : lockAt(i).id());
+        }
+        properties.put("locks", str.toString());
+        properties.put("rethrowException", rethrowException);
+        return properties;
+    }
+
+    @Override
+    public void delete() {
+        FrameState outerFrameState = outerFrameState();
+        super.delete();
+        if (outerFrameState != null && outerFrameState.usages().isEmpty()) {
+            outerFrameState.delete();
+        }
+    }
+
+    @Override
+    public void setRethrowException(boolean b) {
+        rethrowException = b;
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new FrameState(method, bci, localsSize, stackSize, locksSize, rethrowException, into);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameStateAccess.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,55 @@
+/*
+ * 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.max.graal.compiler.value;
+
+import com.oracle.max.graal.compiler.ir.*;
+
+public interface FrameStateAccess {
+
+    FrameState duplicate(int newBci);
+
+    int localsSize();
+
+    int stackSize();
+
+    int locksSize();
+
+    boolean rethrowException();
+
+    Value valueAt(int i);
+
+    Value localAt(int i);
+
+    Value lockAt(int i);
+
+    Value stackAt(int i);
+
+    void setValueAt(int j, Value v);
+
+    void setRethrowException(boolean b);
+
+    Value outerFrameState();
+
+    FrameState duplicateWithException(int bci, Value exceptionObject);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameStateBuilder.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,532 @@
+/*
+ * 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.max.graal.compiler.value;
+
+import static com.oracle.max.graal.compiler.value.ValueUtil.*;
+import static java.lang.reflect.Modifier.*;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.ir.Phi.PhiType;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+
+public class FrameStateBuilder implements FrameStateAccess {
+
+    private final Graph graph;
+
+    private final Value[] locals;
+    private final Value[] stack;
+    private final ArrayList<Value> locks;
+
+    private int stackIndex;
+    private boolean rethrowException;
+
+    private final RiMethod method;
+
+    public FrameStateBuilder(RiMethod method, Graph graph) {
+        assert graph != null;
+        this.method = method;
+        this.graph = graph;
+        this.locals = new Value[method.maxLocals()];
+        // we always need at least one stack slot (for exceptions)
+        int stackSize = Math.max(1, method.maxStackSize());
+        this.stack = new Value[stackSize];
+
+        int javaIndex = 0;
+        int index = 0;
+        if (!isStatic(method.accessFlags())) {
+            // add the receiver and assume it is non null
+            Local local = new Local(method.holder().kind(), javaIndex, graph);
+            local.setDeclaredType(method.holder());
+            storeLocal(javaIndex, local);
+            javaIndex = 1;
+            index = 1;
+        }
+        RiSignature sig = method.signature();
+        int max = sig.argumentCount(false);
+        RiType accessingClass = method.holder();
+        for (int i = 0; i < max; i++) {
+            RiType type = sig.argumentTypeAt(i, accessingClass);
+            CiKind kind = type.kind().stackKind();
+            Local local = new Local(kind, index, graph);
+            if (type.isResolved()) {
+                local.setDeclaredType(type);
+            }
+            storeLocal(javaIndex, local);
+            javaIndex += kind.sizeInSlots();
+            index++;
+        }
+        this.locks = new ArrayList<Value>();
+    }
+
+    @Override
+    public String toString() {
+        return String.format("FrameStateBuilder[stackSize=%d]", stackIndex);
+    }
+
+    public void initializeFrom(FrameState other) {
+        assert locals.length == other.localsSize() : "expected: " + locals.length + ", actual: " + other.localsSize();
+        assert stack.length >= other.stackSize() : "expected: <=" + stack.length + ", actual: " + other.stackSize();
+
+        this.stackIndex = other.stackSize();
+        for (int i = 0; i < other.localsSize(); i++) {
+            locals[i] = other.localAt(i);
+        }
+        for (int i = 0; i < other.stackSize(); i++) {
+            stack[i] = other.stackAt(i);
+        }
+        locks.clear();
+        for (int i = 0; i < other.locksSize(); i++) {
+            locks.add(other.lockAt(i));
+        }
+        this.rethrowException = other.rethrowException();
+    }
+
+    public FrameState create(int bci) {
+        return new FrameState(method, bci, locals, stack, stackIndex, locks, rethrowException, graph);
+    }
+
+    public FrameState duplicateWithException(int bci, Value exceptionObject) {
+        FrameState frameState = new FrameState(method, bci, locals, new Value[]{exceptionObject}, 1, locks, true, graph);
+        frameState.setOuterFrameState(outerFrameState());
+        return frameState;
+    }
+
+    /**
+     * Pushes an instruction onto the stack with the expected type.
+     * @param kind the type expected for this instruction
+     * @param x the instruction to push onto the stack
+     */
+    public void push(CiKind kind, Value x) {
+        assert kind != CiKind.Void;
+        xpush(assertKind(kind, x));
+        if (kind.sizeInSlots() == 2) {
+            xpush(null);
+        }
+    }
+
+    /**
+     * Pushes a value onto the stack without checking the type.
+     * @param x the instruction to push onto the stack
+     */
+    public void xpush(Value x) {
+        assert x == null || !x.isDeleted();
+        stack[stackIndex++] = x;
+    }
+
+    /**
+     * Pushes a value onto the stack and checks that it is an int.
+     * @param x the instruction to push onto the stack
+     */
+    public void ipush(Value x) {
+        xpush(assertInt(x));
+    }
+
+    /**
+     * Pushes a value onto the stack and checks that it is a float.
+     * @param x the instruction to push onto the stack
+     */
+    public void fpush(Value x) {
+        xpush(assertFloat(x));
+    }
+
+    /**
+     * Pushes a value onto the stack and checks that it is an object.
+     * @param x the instruction to push onto the stack
+     */
+    public void apush(Value x) {
+        xpush(assertObject(x));
+    }
+
+    /**
+     * Pushes a value onto the stack and checks that it is a word.
+     * @param x the instruction to push onto the stack
+     */
+    public void wpush(Value x) {
+        xpush(assertWord(x));
+    }
+
+    /**
+     * Pushes a value onto the stack and checks that it is a JSR return address.
+     * @param x the instruction to push onto the stack
+     */
+    public void jpush(Value x) {
+        xpush(assertJsr(x));
+    }
+
+    /**
+     * Pushes a value onto the stack and checks that it is a long.
+     *
+     * @param x the instruction to push onto the stack
+     */
+    public void lpush(Value x) {
+        xpush(assertLong(x));
+        xpush(null);
+    }
+
+    /**
+     * Pushes a value onto the stack and checks that it is a double.
+     * @param x the instruction to push onto the stack
+     */
+    public void dpush(Value x) {
+        xpush(assertDouble(x));
+        xpush(null);
+    }
+
+    public void pushReturn(CiKind kind, Value x) {
+        if (kind != CiKind.Void) {
+            push(kind.stackKind(), x);
+        }
+    }
+
+    /**
+     * Pops an instruction off the stack with the expected type.
+     * @param kind the expected type
+     * @return the instruction on the top of the stack
+     */
+    public Value pop(CiKind kind) {
+        assert kind != CiKind.Void;
+        if (kind.sizeInSlots() == 2) {
+            xpop();
+        }
+        return assertKind(kind, xpop());
+    }
+
+    /**
+     * Pops a value off of the stack without checking the type.
+     * @return x the instruction popped off the stack
+     */
+    public Value xpop() {
+        Value result = stack[--stackIndex];
+        assert result == null || !result.isDeleted();
+        return result;
+    }
+
+    /**
+     * Pops a value off of the stack and checks that it is an int.
+     * @return x the instruction popped off the stack
+     */
+    public Value ipop() {
+        return assertInt(xpop());
+    }
+
+    /**
+     * Pops a value off of the stack and checks that it is a float.
+     * @return x the instruction popped off the stack
+     */
+    public Value fpop() {
+        return assertFloat(xpop());
+    }
+
+    /**
+     * Pops a value off of the stack and checks that it is an object.
+     * @return x the instruction popped off the stack
+     */
+    public Value apop() {
+        return assertObject(xpop());
+    }
+
+    /**
+     * Pops a value off of the stack and checks that it is a word.
+     * @return x the instruction popped off the stack
+     */
+    public Value wpop() {
+        return assertWord(xpop());
+    }
+
+    /**
+     * Pops a value off of the stack and checks that it is a JSR return address.
+     * @return x the instruction popped off the stack
+     */
+    public Value jpop() {
+        return assertJsr(xpop());
+    }
+
+    /**
+     * Pops a value off of the stack and checks that it is a long.
+     * @return x the instruction popped off the stack
+     */
+    public Value lpop() {
+        assertHigh(xpop());
+        return assertLong(xpop());
+    }
+
+    /**
+     * Pops a value off of the stack and checks that it is a double.
+     * @return x the instruction popped off the stack
+     */
+    public Value dpop() {
+        assertHigh(xpop());
+        return assertDouble(xpop());
+    }
+
+    /**
+     * Pop the specified number of slots off of this stack and return them as an array of instructions.
+     * @param size the number of arguments off of the stack
+     * @return an array containing the arguments off of the stack
+     */
+    public Value[] popArguments(int size) {
+        int base = stackIndex - size;
+        Value[] r = new Value[size];
+        for (int i = 0; i < size; ++i) {
+            assert stack[base + i] != null || stack[base + i - 1].kind.jvmSlots == 2;
+            r[i] = stack[base + i];
+        }
+        stackIndex = base;
+        return r;
+    }
+
+    public CiKind peekKind() {
+        Value top = stackAt(stackSize() - 1);
+        if (top == null) {
+            top = stackAt(stackSize() - 2);
+            assert top != null;
+            assert top.kind.isDoubleWord();
+        }
+        return top.kind;
+    }
+
+    /**
+     * Truncates this stack to the specified size.
+     * @param size the size to truncate to
+     */
+    public void truncateStack(int size) {
+        stackIndex = size;
+        assert stackIndex >= 0;
+    }
+
+    /**
+     * Clears all values on this stack.
+     */
+    public void clearStack() {
+        stackIndex = 0;
+    }
+
+    /**
+     * Loads the local variable at the specified index.
+     *
+     * @param i the index of the local variable to load
+     * @return the instruction that produced the specified local
+     */
+    public Value loadLocal(int i) {
+        Value x = locals[i];
+        if (x != null) {
+            if (x instanceof Phi) {
+                assert ((Phi) x).type() == PhiType.Value;
+                if (x.isDeleted()) {
+                    return null;
+                }
+            }
+            assert x.kind.isSingleWord() || locals[i + 1] == null || locals[i + 1] instanceof Phi;
+        }
+        return x;
+    }
+
+    /**
+     * Stores a given local variable at the specified index. If the value is a {@linkplain CiKind#isDoubleWord() double word},
+     * then the next local variable index is also overwritten.
+     *
+     * @param i the index at which to store
+     * @param x the instruction which produces the value for the local
+     */
+    public void storeLocal(int i, Value x) {
+        locals[i] = x;
+        if (isDoubleWord(x)) {
+            // (tw) if this was a double word then kill i+1
+            locals[i + 1] = null;
+        }
+        if (i > 0) {
+            // if there was a double word at i - 1, then kill it
+            Value p = locals[i - 1];
+            if (isDoubleWord(p)) {
+                locals[i - 1] = null;
+            }
+        }
+    }
+
+    /**
+     * Locks a new object within the specified IRScope.
+     * @param scope the IRScope in which this locking operation occurs
+     * @param obj the object being locked
+     */
+    public void lock(Value obj) {
+        locks.add(obj);
+    }
+
+    /**
+     * Unlock the lock on the top of the stack.
+     */
+    public void unlock() {
+        locks.remove(locks.size() - 1);
+    }
+
+    /**
+     * Get the value on the stack at the specified stack index.
+     *
+     * @param i the index into the stack, with {@code 0} being the bottom of the stack
+     * @return the instruction at the specified position in the stack
+     */
+    public final Value stackAt(int i) {
+        return stack[i];
+    }
+
+    /**
+     * Gets the value in the local variables at the specified index.
+     *
+     * @param i the index into the locals
+     * @return the instruction that produced the value for the specified local
+     */
+    public final Value localAt(int i) {
+        return locals[i];
+    }
+
+    /**
+     * Retrieves the lock at the specified index in the lock stack.
+     * @param i the index into the lock stack
+     * @return the instruction which produced the object at the specified location in the lock stack
+     */
+    public final Value lockAt(int i) {
+        return locks.get(i);
+    }
+
+    /**
+     * Returns the size of the local variables.
+     *
+     * @return the size of the local variables
+     */
+    public int localsSize() {
+        return locals.length;
+    }
+
+    /**
+     * Gets number of locks held by this frame state.
+     */
+    public int locksSize() {
+        return locks.size();
+    }
+
+    /**
+     * Gets the current size (height) of the stack.
+     */
+    public int stackSize() {
+        return stackIndex;
+    }
+
+    public Iterator<Value> locals() {
+        return new ValueArrayIterator(locals);
+    }
+
+    public Iterator<Value> stack() {
+        return new ValueArrayIterator(locals);
+    }
+
+    public List<Value> locks() {
+        return Collections.unmodifiableList(locks);
+    }
+
+
+    private static class ValueArrayIterator implements Iterator<Value> {
+        private final Value[] array;
+        private int index;
+        private int length;
+
+        public ValueArrayIterator(Value[] array, int length) {
+            assert length <= array.length;
+            this.array = array;
+            this.index = 0;
+        }
+
+        public ValueArrayIterator(Value[] array) {
+            this(array, array.length);
+        }
+
+        @Override
+        public boolean hasNext() {
+            return index < array.length;
+        }
+
+        @Override
+        public Value next() {
+            return array[index++];
+        }
+
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException("cannot remove from array");
+        }
+
+    }
+
+
+    @Override
+    public FrameState duplicate(int bci) {
+        return create(bci);
+    }
+
+    @Override
+    public Value valueAt(int i) {
+        if (i < locals.length) {
+            return locals[i];
+        } else if (i < locals.length + stackIndex) {
+            return stack[i - locals.length];
+        } else {
+            return locks.get(i - locals.length - stack.length);
+        }
+    }
+
+    @Override
+    public void setValueAt(int i, Value v) {
+        if (i < locals.length) {
+            locals[i] = v;
+        } else if (i < locals.length + stackIndex) {
+            stack[i - locals.length] = v;
+        } else {
+            locks.set(i - locals.length - stack.length, v);
+        }
+    }
+
+    @Override
+    public FrameState outerFrameState() {
+        return null;
+    }
+
+    public FrameState duplicateWithoutStack(int bci) {
+        FrameState frameState = new FrameState(method, bci, locals, new Value[0], 0, locks, false, graph);
+        frameState.setOuterFrameState(outerFrameState());
+        return frameState;
+    }
+
+    @Override
+    public boolean rethrowException() {
+        return rethrowException;
+    }
+
+    @Override
+    public void setRethrowException(boolean b) {
+        rethrowException = b;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/ValueUtil.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,84 @@
+/*
+ * 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.max.graal.compiler.value;
+
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.sun.cri.ci.*;
+
+
+public class ValueUtil {
+
+    public static Value assertKind(CiKind kind, Value x) {
+        assert x != null && (x.kind == kind) : "kind=" + kind + ", value=" + x + ((x == null) ? "" : ", value.kind=" + x.kind);
+        return x;
+    }
+
+    public static Value assertLong(Value x) {
+        assert x != null && (x.kind == CiKind.Long);
+        return x;
+    }
+
+    public static Value assertJsr(Value x) {
+        assert x != null && (x.kind == CiKind.Jsr);
+        return x;
+    }
+
+    public static Value assertInt(Value x) {
+        assert x != null && (x.kind == CiKind.Int);
+        return x;
+    }
+
+    public static Value assertFloat(Value x) {
+        assert x != null && (x.kind == CiKind.Float);
+        return x;
+    }
+
+    public static Value assertObject(Value x) {
+        assert x != null && (x.kind == CiKind.Object);
+        return x;
+    }
+
+    public static Value assertWord(Value x) {
+        assert x != null && (x.kind == CiKind.Word);
+        return x;
+    }
+
+    public static Value assertDouble(Value x) {
+        assert x != null && (x.kind == CiKind.Double);
+        return x;
+    }
+
+    public static void assertHigh(Value x) {
+        assert x == null;
+    }
+
+    public static boolean typeMismatch(Value x, Value y) {
+        return y == null || !Util.archKindsEqual(x, y);
+    }
+
+    public static boolean isDoubleWord(Value x) {
+        return x != null && x.kind.isDoubleWord();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/package-info.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2010, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @author Ben Titzer
+ */
+package com.oracle.max.graal.compiler.value;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/extensions/FrameModifier.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.extensions;
+
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+
+public interface FrameModifier {
+    CiFrame getFrame(RiRuntime runtime, CiFrame frame);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/extensions/InliningGuide.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.extensions;
+
+import com.sun.cri.ri.*;
+
+
+public interface InliningGuide {
+    InliningHint getHint(int depth, RiMethod caller, int bci, RiMethod target);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/extensions/InliningHint.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.extensions;
+
+
+public enum InliningHint {
+    NONE,
+    NEVER,
+    LESS,
+    MORE,
+    ALWAYS
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/extensions/Intrinsifier.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.extensions;
+
+import java.util.*;
+
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ri.*;
+
+
+public interface Intrinsifier {
+    Graph intrinsicGraph(RiRuntime runtime, RiMethod caller, int bci, RiMethod method, List<? extends Node> parameters);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/extensions/Optimizer.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.extensions;
+
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ri.*;
+
+
+public interface Optimizer {
+    void optimize(RiRuntime runtime, Graph graph);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.doc.initial/.project	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>com.oracle.max.graal.doc.initial</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>net.sourceforge.texlipse.builder.TexlipseBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>net.sourceforge.texlipse.builder.TexlipseNature</nature>
+	</natures>
+	<linkedResources>
+		<link>
+			<name>fleqn.clo</name>
+			<type>1</type>
+			<location>C:/Program Files (x86)/MiKTeX 2.8/tex/latex/base/fleqn.clo</location>
+		</link>
+	</linkedResources>
+</projectDescription>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.doc.initial/.texlipse	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,13 @@
+#TeXlipse project settings
+#Fri Apr 29 14:13:11 CEST 2011
+builderNum=2
+outputDir=
+makeIndSty=
+bibrefDir=
+outputFormat=pdf
+tempDir=tmp
+mainTexFile=graal_compiler.tex
+outputFile=graal_compiler.pdf
+langSpell=en
+markDer=true
+srcDir=
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.doc.initial/graal_compiler.tex	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,870 @@
+\documentclass[twocolumn]{svjour3}
+\usepackage{listings}
+\usepackage[pdftex]{graphicx}
+\usepackage{environ}
+\usepackage{amsmath}
+\usepackage{amsfonts}
+\usepackage[english]{babel}
+\usepackage[utf8]{inputenc} 
+\usepackage{lmodern}
+\usepackage[T1]{fontenc}
+\usepackage{color}
+
+\input{graphdrawing}
+
+\renewcommand*\descriptionlabel[1]{\hspace\labelsep\normalfont\bf #1}
+
+\newcommand{\Sa}{{\Large$^*$}}
+\newcommand{\Sb}{{\Large$^\dag$}}
+\newcommand{\Sc}{{\Large$^\S$}}
+
+
+\newcommand{\mynote}[2]{
+\textcolor{red}{\fbox{\bfseries\sffamily\scriptsize#1}
+  {\small\textsf{\emph{#2}}}
+\fbox{\bfseries\sffamily\scriptsize }}}
+
+\newcommand\TODO[1]{\mynote{TODO}{#1}}
+\newcommand\cw[1]{\mynote{CW}{#1}}
+\newcommand\ls[1]{\mynote{LS}{#1}}
+\newcommand\nodename[1]{\texttt{#1}}
+
+\hyphenpenalty=0
+\doublehyphendemerits=0
+\finalhyphendemerits=0
+\clubpenalty10000
+\widowpenalty10000
+
+
+\smartqed  % flush right qed marks, e.g. at end of proof
+
+\journalname{Graal Compiler Design}
+\def\makeheadbox{{%
+\hbox to0pt{\vbox{\baselineskip=10dd\hrule\hbox
+to\hsize{\vrule\kern3pt\vbox{\kern3pt
+\hbox{\bfseries The Graal Compiler - Design and Strategy}
+\kern3pt}\hfil\kern3pt\vrule}\hrule}%
+\hss}}}
+
+\begin{document}
+
+\author{Thomas W\"{u}rthinger \Sa, Lukas Stadler \Sc, Gilles Duboscq \Sa}
+\institute{\Sa Oracle, \Sc Johannes Kepler University, Linz}
+
+\date{Created: \today}
+
+\title{The Graal Compiler}
+\subtitle{Design and Strategy \\ \textcolor{red}{work in progress (Oracle internal)}}
+
+\maketitle
+
+\abstract{
+The Graal compiler (simply referred to as \emph{the compiler} in the rest of this document) aims at improving upon C1X, the Java port of the HotSpot client compiler, both in terms of modularity and peak performance.
+The compiler should work with the Maxine VM and the HotSpot VM.
+This document contains information about the proposed design and strategy for developing the compiler.}
+
+\section{Context}
+
+In 2009, the Maxine team started with creating C1X, a Java port of the HotSpot client compiler, and integrated it into the Maxine VM.
+Part of this effort was the development of a clear and clean compiler-runtime interface that allows the separation of the compiler and the VM.
+This compiler-runtime interface enables the use of one compiler for multiple VMs.
+In June 2010, we started integrating C1X into the HotSpot VM and we called the resulting system Graal~VM.
+Currently, the Graal~VM is fully functional and runs benchmarks (SciMark, DaCapo) at a similar speed as the HotSpot client compiler.
+
+\section{Goals}
+The compiler effort aims at rewriting the high-level intermediate representation of C1X with two main goals:
+\begin{description}
+\item[Modularity:]
+A modular design of the compiler should simplify the implementation of new languages, new back-ends, and new optimizations.
+\item[Peak Performance:]
+A more powerful intermediate representation should enable the implementation of aggressive optimizations that impact the peak performance of the resulting machine code.
+In terms of startup performance, we want to orientate ourselves to the HotSpot server compiler configuration.
+\end{description}
+
+\section{Design}
+For the implementation of the compiler, we rely on the following design decisions:
+\begin{description}
+\item[Graph Representation:]
+The compiler's intermediate representation is modeled as a graph with nodes that are connected with directed edges.
+There is only a single node base class and every node has an associated graph object that does not change during the node's lifetime.
+Every node is serializable and has an id that is unique within its graph.
+Every edge is classified as either a control flow edge (anti-dependency) or a data flow edge (dependency) and represented as a simple pointer from the source node to the target node.
+It is possible to replace a node with another node without traversing the full graph.
+The graph does not allow data flow edge cycles or control flow edge cycles.
+We achieve this by explicitly modeling loops (see Section~\ref{sec:loops}). 
+\item[Extensibility:]
+The compiler is extensible by allowing developers to add new compiler phases and new node subclasses without modifying the compiler's sources.
+A node has an abstract way of expressing its semantics and new compiler phases can ask compiler nodes for their properties and capabilities.
+We use the ``everything is an extension'' concept.
+Even standard compiler optimizations are internally modeled as extensions, to show that the extension mechanism exposes all necessary functionality.
+\item[Detailing:]
+The compilation starts with a graph that contains nodes that represent the operations of the source language (e.g., one node for an array store to an object array).
+During the compilation, the nodes are replaced with more detailed nodes (e.g., the array store node is split into a null check, a bounds check, a store check, and a memory access).
+Compiler phases can choose whether they want to work on the earlier versions of the graph (e.g., escape analysis) or on later versions (e.g., null check elimination).
+\item[Generality:]
+The compiler does not require Java as its input.
+This is achieved by having a graph as the starting point of the compilation and not a Java bytecode array.
+Building the graph from the Java bytecodes must happen before giving a method to the compiler.
+This enables front-ends for different languages (e.g., Ruby or JavaScript) to provide their own graph.
+The support for different languages is constrained by the following two conditions: We only support structured control flow, and the dynamic type system of the language must be expressible using the RiType class.
+Also, there is no dependency on a specific back-end, but the output of the compiler is a graph that can then be converted to a different representation in a final compiler phase.
+\end{description}
+
+\section{Milestones}
+\label{sec:mile}
+The compiler is being developed starting from the current C1X source code base.
+This helps us test the compiler at every intermediate development step on a variety of Java benchmarks.
+We define the following development milestones (see Section~\ref{sec:conclusions} for planned dates):
+\begin{description}
+\item[M1:] We have a fully working Graal~VM version with a stripped down C1X compiler that does not perform any optimization.
+\item[M2:] We modified the high-level intermediate representation to be based on the compiler graph data structure.
+\item[M3:] We have reimplemented and reenabled compiler optimizations in the compiler that previously existed in C1X.
+\item[M4:] We have reintegrated the new compiler into the Maxine VM and can use it as a Maxine VM bootstrapping compiler.
+\end{description}
+
+After those four milestones, we see three different possible further development directions that can be followed in parallel:
+\begin{itemize}
+  \item Removal of the XIR template mechanism and replacement with a snippet mechanism that works with the compiler graph.
+  \item Improvements for peak performance (loop optimizations, escape analysis, bounds check elimination, processing additional interpreter runtime feedback).
+  \item Implementation of a prototype front-end for a different language, e.g., JavaScript.
+\end{itemize}
+
+\section{Project Source Structure}
+In order to support the goal of a modular compiler, the code will be divided into the following source code projects (as subprojects of \textbf{com.oracle.max.graal}).
+
+\begin{description}
+    \item[graph] contains the abstract node implementation, the graph implementation and all the associated tools and auxiliary classes.
+    \item[nodes] contains the implementation of known basic nodes (e.g., phi nodes, control flow nodes, \ldots).
+ 				 Additional node classes should go into separate projects and be specializations of the known basic nodes.
+    \item[java] contains code for building graphs from Java bytecodes and Java-specific nodes.
+    \item[opt] contains optimizations such as global value numbering or conditional constant propagation.
+    \item[compiler] contains the compiler, including:
+        \begin{itemize}
+            \item Scheduling of the compilation phases.
+            \item Implementation of the \emph{compiler interface} (CI).
+            \item Implementation of the final compilation phase that produces the low-level representation.
+            \item Machine code creation, including debug info.
+        \end{itemize}
+\end{description}
+
+
+\section{Graph}
+
+The \emph{intermediate representation}~(IR) of the compiler is designed as a directed graph.
+The graph allocates unique ids for new nodes and can be queried for the node corresponding to a given id as well as for an unordered list of nodes of the graph.
+Graphs can manage side data structures (e.g. dominator trees and temporary schedules), which will be automatically invalidated and lazily recomputed whenever the graph changes. These side data structures will usually be understood by more than one optimization.
+
+The nodes of the graph have the following properties:
+\begin{itemize}
+    \item Each node is always associated with a single graph and this association is immutable.
+    \item Each node has an immutable id that is unique within its associated graph.
+    \item Nodes can have a data dependency, which means that one node requires the result of another node as its input. The fact that the result of the first node needs to be computed before the second node can be executed introduces a partial order to the set of nodes.
+    \item Nodes can have a control flow dependency, which means that the execution of one node will be followed by the execution of another node. This includes conditional execution, memory access serialization and other reasons, and again introduces a partial order to the set of nodes.
+    \item Nodes can only have data and control dependencies to nodes which belong to the same graph.
+    \item Control dependencies and data dependencies each represent a \emph{directed acyclic graph} (DAG) on the same set of nodes. This means that data dependencies always point upwards, and control dependencies always point downwards in a drawing of the graph. Situations that normally incur cycles (like loops) are represented by special nodes (see Section~\ref{sec:loops}).
+	\item Ordering between nodes is specified only to the extent which is required to correctly express the semantics of a given program. This gives the compiler flexibility for the possible scheduling of a node and therefore wiggle room for optimizations. For algorithms that require a fixed ordering of nodes, a temporary schedule can always be generated.
+    \item Both data and control dependencies can be traversed in both directions, so that each node can be traversed in four directions (see Figure~\ref{fig:directions}):
+    \begin{itemize}
+        \item \emph{inputs} are all nodes that this node has data dependencies on.
+        \item \emph{usages} are all nodes whose inputs contain this node.
+        \item \emph{successors} are all nodes that have to be after this node in control flow.
+        \item \emph{predecessors} are all nodes whose successors contain this node.
+    \end{itemize}
+    \item Only inputs and successors can be changed, and changes to them will update the usages and predecessors.
+    \item Every node must be able to support cloning and serialization.
+    \item The edges of a node also define \textit{emitted-before} and \textit{emitted-after} relationships as shown in Figure~\ref{fig:directions}.
+    They mean that the machine code for one node is emitted before or after the machine code of another node.
+\end{itemize}
+
+\begin{figure}[ht]
+  \centering
+\begin{digraphenv}{scale=0.5}{graphdirections}
+\node{node1}{Node}
+\textnode{inputs}{inputs}
+\textnode{usages}{usages}
+\textnode{successors}{successors}
+\textnode{predecessors}{predecessors}
+\data{node1}{inputs}
+\control{node1}{successors}
+\data{usages}{node1}
+\control{predecessors}{node1}
+\node{node2}{Node}
+\textnode{before}{emitted-before}
+\textnode{after}{emitted-after}
+\data{node2}{before}
+\control{node2}{after}
+\data{after}{node2}
+\control{before}{node2}
+\end{digraphenv}
+  \caption{A node and its edges.}
+  \label{fig:directions}
+\end{figure}
+
+\subsection{Inlining}
+Inlining is always performed by embedding one graph into another graph.
+Nodes cannot be reassigned to another graph, they are cloned instead.
+Therefore, inlining is performed by copying and rewiring the nodes of the inlined method into the graph of the outer method.
+While the copying will decrease compilation performance, it enables us to cache the graph for the inlined method, optimize it independently from the outer method, and use the optimized graph for subsequent inlinings.
+We do not expect a significant negative impact on overall compilation performance.
+
+We are able to perform the inlining at any point during the compilation of a method and can therefore selectively expand the inlining if a certain optimization turns out to depend on the inlining of a method.
+An example for this would be when the escape analysis finds out that a certain object only escapes because of one method call and this method call is not inlined, because the penalty was to high.
+In this case, we can chose to nevertheless inline the method in order to increase the chances for finding out that the object does not escape.
+
+\section{Control Flow}
+
+Control flow is managed in a way where the predecessor node contains direct pointers to its successor nodes.
+This is opposite to the approach taken in the server compiler, where control flow and data flow edges point in the same direction.
+The advantage that we see in our approach is that there is no need for projection nodes in case of control flow splits.
+An \texttt{If} node can directly point to its true and false successors without any intermediate nodes.
+This makes the graph more compact and simplifies graph traversal.
+We distinguish between \textit{fixed nodes} that are directly embedded in the control flow and \textit{floating nodes} whose position in the control flow may vary.
+
+Listing~\ref{lst:cfg2} shows an example Java program with an if statement where both paths do not contain any node with side effects.
+Figure~\ref{fig:loopexits} shows the corresponding compiler graph.
+The \texttt{If} node can directly point its true and false successors to a \texttt{Merge} node.
+A \texttt{Phi} node that selects the appropriate value is appended to the \texttt{Merge} node.
+The \texttt{Return} node then has a data dependency on the \texttt{Phi} node.
+
+\begin{lstlisting}[label=lst:cfg2, caption=Control flow in the graph., captionpos=b]
+if (condition) { return 0; }
+else { return 1; }
+\end{lstlisting}
+
+\begin{figure}[ht]
+  \centering
+\begin{digraphenv}{scale=0.5}{cfg2}
+\textnode{entry}{Entry}
+\textnode{condition}{condition}
+\textnode{const0}{0}
+\textnode{const1}{1}
+\nodesplit{if}{If}
+\control{entry}{if}
+\controllabel{if:succ1}{merge}
+\controllabel{if:succ2}{merge}
+\data{if}{condition}
+\node{merge}{Merge}
+\node{return}{Return}
+\nodetri{phi}{Phi}
+\datalabel{phi:in1}{merge}
+\datalabel{phi:in2}{const0}
+\datalabel{phi:in3}{const1}
+\data{return}{phi}
+\control{merge}{return}
+\end{digraphenv}
+  \caption{A simple loop with two exits.}
+  \label{fig:loopexits}
+\end{figure}
+
+\section{Exceptions}
+\label{sec:Exceptions}
+
+We do not throw runtime exceptions (e.g., \texttt{IndexOutOf\-BoundsException}, \texttt{Null\-Pointer\-Exception}, or \texttt{Out\-Of\-Memory\-Exception}), but deoptimize instead.
+This reduces the places in the compiled code where an exact bytecode location and debug information must be known.
+Additionally, this greatly reduces the number of exception handler edges in the compiled code.
+The main advantage of this technique is however, that we are free in moving around bounds checks, memory allocation, memory accesses with implicit null checks, etc.
+
+There are only two kinds of nodes that need explicit exception edges, because they are the only nodes that can throw exceptions in compiled code: \texttt{Throw} nodes and \texttt{Invoke} nodes.
+They are modelled as nodes with an additional control flow continuation that points to an \texttt{ExceptionDispatch} node.
+The exception dispatch node decides based on the type of the exception object whether the control should flow to the catch handler or to another exception dispatch.
+If there is no catch handler in the currently compiled method, then the control flows into the \texttt{Unwind} node that handles the exception by forwarding it to the caller.
+Listing~\ref{lst:exc1} shows an example Java program with nested try blocks and Figure \ref{fig:exc1} shows the corresponding compiler graph.
+
+\begin{lstlisting}[label=lst:exc1, caption=Exception dispatch in the compiler graph., captionpos=b]
+try { m1();
+  try { m2();
+  } catch(ExtendedException e) { ... }
+  m3();
+  throw exception;
+} catch(Exception e) { ... }
+\end{lstlisting}
+
+\begin{figure}[ht]
+  \centering
+\begin{digraphenv}{scale=0.5}{exc1}
+\textnode{entry}{Entry}
+\textnode{catch1}{catch1}
+\textnode{catch2}{catch2}
+\nodesplit{m1}{Invoke m1}
+\nodesplit{m2}{Invoke m2}
+\nodesplit{m3}{Invoke m3}
+\nodesplit{dispatch1}{ExceptionDispatch}
+\nodesplit{dispatch2}{ExceptionDispatch}
+\node{throw}{Throw}
+\node{unwind}{Unwind}
+\control{entry}{m1}
+\controllabel{m1:succ1}{m2}
+\controllabel{m1:succ2}{dispatch2}
+\controllabel{m2:succ1}{m3}
+\controllabel{m2:succ2}{dispatch1}
+\controllabel{m3:succ1}{throw}
+\controllabel{m3:succ2}{dispatch2}
+\control{throw}{dispatch2}
+\controllabel{dispatch1:succ2}{catch1}
+\controllabel{dispatch1:succ1}{dispatch2}
+\controllabel{dispatch2:succ2}{catch2}
+\controllabel{dispatch2:succ1}{unwind}
+\end{digraphenv}
+  \caption{A simple loop with two exits.}
+  \label{fig:exc1}
+\end{figure}
+
+\section{Loops}
+\label{sec:loops}
+Loops form a first-class construct in the IR that is expressed by specialized IR nodes during all optimization phases.
+We only compile methods with a control flow where every loop has a single entry point.
+This entry point is a \nodename{LoopBegin} node.
+This node is connected to a \nodename{LoopEnd} node that merges all control flow paths that do not exit the loop.
+The edge between the \nodename{LoopBegin} and the \nodename{LoopEnd} is the backedge of the loop.
+It goes from the beginning to the end in order to make the graph acyclic.
+An algorithm that traverses the control flow has to explicitely decide whether it wants to incorporate backedges (i.e., special case of the treatment of \nodename{LoopEnd}) or ignore them.
+Figure \ref{fig:loop1} shows a simple example with a loop with a single entry and two exits.
+
+\begin{figure}[ht]
+  \centering
+\begin{digraphenv}{scale=0.5}{layout1}
+\textnode{BeforeLoop}{Loop entry}
+\textnode{Exit1}{First loop exit}
+\textnode{Exit2}{Second loop exit}
+\node{LoopBegin}{LoopBegin}
+\node{LoopEnd}{LoopEnd}
+\nodesplit{If1}{If}
+\nodesplit{If2}{If}
+\data{LoopEnd}{LoopBegin}
+\control{LoopBegin}{If1}
+\controllabel{If1:succ1}{If2}
+\controllabel{If2:succ1}{LoopBody}
+\textnode{LoopBody}{Loop body}
+\control{LoopBody}{LoopEnd}
+\controllabel{BeforeLoop}{LoopBegin}
+\controllabel{If1:succ2}{Exit1}
+\controllabel{If2:succ2}{Exit2}
+\end{digraphenv}
+  \caption{A simple loop with two exits.}
+  \label{fig:loop1}
+\end{figure}
+
+\subsection{Loop Phis}
+Data flow in loops is modeled with special phi nodes at the beginning and the end of the loop.
+The \nodename{LoopEnd} node merges every value that flows into the next loop iteration in associated \nodename{LoopEndPhi} nodes.
+A corresponding \nodename{LoopBeginPhi} node that is associated with the loop header has a control flow dependency on the \nodename{LoopEndPhi} node.
+Listing~\ref{lst:loop} shows a simple counting loop that is used as an example in the rest of this section.
+Figure~\ref{fig:loop2} shows how the loop is modelled immediately after building the graph.
+
+\begin{lstlisting}[label=lst:loop, caption=Loop example that counts from 0 to n-1., captionpos=b]
+for(int i=0; i<n; ++i) { }
+\end{lstlisting}
+
+\begin{figure}[ht]
+  \centering
+\begin{digraphenv}{scale=0.5}{layout2}
+\textnode{BeforeLoop}{Loop entry}
+\textnode{Exit}{Loop exit}
+\textnode{n}{n}
+\textnode{Constant0}{0}
+\textnode{Constant1}{1}
+\node{LoopBegin}{LoopBegin}
+\node{LoopEnd}{LoopEnd}
+\nodesplit{If1}{If}
+\data{LoopEnd}{LoopBegin}
+\control{LoopBegin}{If1}
+\nodebi{Compare}{&lt;}
+\nodebi{LoopBeginPhi}{LoopBeginPhi}
+\nodebi{Add}{+}
+\datalabel{Add:in1}{LoopBeginPhi}
+\datalabel{Add:in2}{Constant1}
+\nodebi{LoopEndPhi}{LoopEndPhi}
+\control{LoopBeginPhi}{LoopEndPhi}
+\data{LoopEndPhi:in1}{LoopEnd}
+\data{LoopEndPhi:in2}{Add}
+\datalabel{LoopBeginPhi:in1}{LoopBegin}
+\datalabel{LoopBeginPhi:in2}{Constant0}
+\datalabel{Compare:in1}{LoopBeginPhi}
+\datalabel{Compare:in2}{n}
+\data{If1}{Compare}
+\controllabel{If1:succ1}{LoopBody}
+\textnode{LoopBody}{Loop body}
+\control{LoopBody}{LoopEnd}
+\controllabel{BeforeLoop}{LoopBegin}
+\controllabel{If1:succ2}{Exit}
+\end{digraphenv}
+  \caption{Graph for a loop counting from 0 to n-1.}
+  \label{fig:loop2}
+\end{figure}
+
+\subsection{Loop Counters}
+The compiler is capable of recognizing variables that are only increased within a loop.
+A potential overflow of such a variable is prohibited with a guard before the loop (this is not necessary in this example, because the loop variable cannot overflow).
+Figure \ref{fig:loop3} shows the compiler graph of the example loop after the loop counter transformation.
+
+
+\begin{figure}[ht]
+  \centering
+\begin{digraphenv}{scale=0.5}{layout3}
+\textnode{BeforeLoop}{Loop entry}
+\textnode{Exit}{Loop exit}
+\textnode{n}{n}
+\textnode{Constant0}{0}
+\textnode{Constant1}{1}
+\node{LoopBegin}{LoopBegin}
+\node{LoopEnd}{LoopEnd}
+\nodesplit{If1}{If}
+\data{LoopEnd}{LoopBegin}
+\control{LoopBegin}{If1}
+\nodebi{Compare}{&lt;}
+\nodetri{LoopCounter}{LoopCounter}
+\datalabel{LoopCounter:in1}{LoopBegin}
+\datalabeltext{LoopCounter:in2}{Constant0}{init}
+\datalabeltext{LoopCounter:in3}{Constant1}{stride}
+\datalabel{Compare:in1}{LoopCounter}
+\datalabel{Compare:in2}{n}
+\data{If1}{Compare}
+\controllabel{If1:succ1}{LoopBody}
+\textnode{LoopBody}{Loop body}
+\control{LoopBody}{LoopEnd}
+\controllabel{BeforeLoop}{LoopBegin}
+\controllabel{If1:succ2}{Exit}
+\end{digraphenv}
+  \caption{Graph after loop counter transformation.}
+  \label{fig:loop3}
+\end{figure}
+
+\subsection{Bounded Loops}
+
+If the total maximum number of iterations of a loop is fixed, then the loop is converted into a bounded loop.
+The total number of iterations always denotes the number of full iterations of the loop with the control flowing from the loop begin to the loop end.
+If the total number of iterations is reached, the loop is exited directly from the loop header.
+The representation of the bounded loop in the graph should support reasoning about the loop, but does not specify how the loop will later be converted to machine code.
+In the example, we can infer from the loop exit with the comparison on the loop counter that the total number of iterations of the loop is limited to n.
+Figure \ref{fig:loop4} shows the compiler graph of the example loop after the bounded loop transformation.
+If there are no other exits out of the loop, then the number of iterations specified as the input to the bounded loop node is also the exact number of loop iterations.
+Loops with the same number of iterations can be merged into a single loop.
+We also want to support loop splitting in order to find simple loops that are candidates for vectorization.
+
+\begin{figure}[ht]
+  \centering
+\begin{digraphenv}{scale=0.5}{layout4}
+\textnode{BeforeLoop}{Loop entry}
+\textnode{Exit}{Loop exit}
+\textnode{n}{n}
+\textnode{Constant0}{0}
+\textnode{Constant1}{1}
+\nodesplit{LoopBegin}{BoundedLoopBegin}
+\node{LoopEnd}{LoopEnd}
+\data{LoopEnd}{LoopBegin}
+\controllabel{LoopBegin:succ1}{LoopBody}
+\textnode{LoopBody}{Loop body}
+\control{LoopBody}{LoopEnd}
+\controllabel{LoopBegin:succ2}{Exit}
+\nodetri{LoopCounter}{LoopCounter}
+\datalabel{LoopCounter:in1}{LoopBegin}
+\datalabeltext{LoopCounter:in2}{Constant0}{init}
+\datalabeltext{LoopCounter:in3}{Constant1}{stride}
+\data{LoopBegin}{n}
+\controllabel{BeforeLoop}{LoopBegin}
+\end{digraphenv}
+  \caption{Graph after bounded loop transformation.}
+  \label{fig:loop4}
+\end{figure}
+
+\subsection{Vectorization}
+
+If we have now a bounded loop with no additional loop exit and no associated phi nodes (only associated loop counters), we can vectorize the loop.
+We replace the loop header with a normal node that produces a vector of values from 0 to the number of loop iterations minus 1.
+The loop counters are replaced with \texttt{VectorAdd} and \texttt{VectorMul} nodes.
+The vectorization is only possible if every node of the loop can be replaced with a corresponding vector node.
+Figure \ref{fig:loop5} shows the compiler graph of the example loop after vectorization.
+The vector nodes all work on an ordered list of integer values and are subject to canonicalization and global value numbering like any other node.
+
+
+\begin{figure}[ht]
+  \centering
+\begin{digraphenv}{scale=0.5}{layout5}
+\textnode{Entry}{Entry}
+\textnode{Exit}{Exit}
+\textnode{n}{n}
+\textnode{Constant0}{0}
+\textnode{Constant1}{1}
+\node{Vector}{Vector}
+\nodebi{VectorAdd}{VectorAdd}
+\nodebi{VectorMul}{VectorMul}
+\control{Entry}{Vector}
+\control{Vector}{Exit}
+\datalabel{VectorAdd:in1}{Vector}
+\datalabel{VectorAdd:in2}{Constant0}
+\datalabel{VectorMul:in1}{VectorAdd}
+\datalabel{VectorMul:in2}{Constant1}
+\data{Vector}{n}
+\end{digraphenv}
+  \caption{Graph after vectorization.}
+  \label{fig:loop5}
+\end{figure}
+
+
+\section{Frame States}
+A frame state captures the state of the program like it is seen in by an interpreter of the program.
+The frame state contains the information that is local to the current activation and will therefore disappear during SSA-form constructions or other compiler optimizations.
+For Java, the frame state is defined in terms of the Java bytecode specification (i.e., the values of the local variables, the operand stack, and the locked monitors).
+However, a frame state is not a concept specific to Java (e.g., the Crankshaft JavaScript engine uses frame states in their optimizing compiler to model the values of the AST interpreter).
+
+Frame states are necessary to support the deoptimization of the program, which is the precondition for performing aggressive optimizations that use optimistic assumptions.
+Therefore every point in the optimizing compiler that may revert execution back to the interpreter needs a valid frame state.
+However, the point where the interpreter continues execution need not correspond exactly to the execution position of the compiled code, because many Java bytecode nodes can be safely reexecuted.
+Thus, frame states need only be generated for the states after nodes that cannot be reexecuted, because they modify the state of the program.
+Examples for such nodes are:
+
+\begin{itemize}
+    \item Array stores (in Java bytecodes {\tt IASTORE, LASTORE, FASTORE, \\DASTORE, AASTORE, BASTORE, CASTORE, SASTORE})
+    \item Field stores (in Java bytecodes {\tt PUTSTATIC, PUTFIELD})
+    \item Method calls (in Java bytecodes {\tt INVOKEVIRTUAL, INVOKESPECIAL, \\INVOKESTATIC, INVOKEINTERFACE})
+    \item Synchronization (in Java bytecodes {\tt MONITORENTER, MONITOREXIT})
+\end{itemize}
+
+Within the graph a frame state is represented as a node that is attached to the node that caused it to be generated using a control dependency (see Figure~\ref{fig:fs1}).
+Frame states also have data dependencies on the contents of the state: the local variables and the expression stack.
+
+The frame state at the method beginning does not have to be explicitely in the graph, because it can always be reconstructed at a later stage.
+We save the frame state at control flow merges if there is at least one frame state on any control flow path between a node and its immediate dominator.
+
+
+\begin{figure}[ht]
+  \centering
+\begin{digraphenv}{scale=0.5}{fs1}
+    \nodetrisplit{store1}{ArrayStore}
+    \nodebi{load1}{ArrayLoad}
+    \controllabel{store1:succ1}{load1}
+    \nodetrisplit{store2}{FieldStore}
+    \control{load1}{store2}
+    end [shape=plaintext, label="...", width="2.0"]
+    store2:succ1:s -> end:n [color=red];
+    %
+    \nodeframestate{fs1}{FrameState}
+    \controllabel{store1:succ2}{fs1}
+    \nodeframestate{fs2}{FrameState}
+    \controllabel{store2:succ2}{fs2}
+\end{digraphenv}
+  \caption{Simple example using two frame states.}
+  \label{fig:fs1}
+\end{figure}
+
+
+A deoptimization node needs a valid frame state that specifies the location and state where the interpreter should continue.
+The algorithm for constructing frame states makes sure that every possible location in the graph has a well-defined frame state that can be used by a deoptimization node.
+Therefore, there are no direct links between the deoptimization node and its frame state thus allowing the deoptimization nodes to move freely around.
+
+\subsection{Partial Escape Analysis}
+
+A partial escape analysis can help to further reduce the number of frame states.
+A field or array store does not create a new frame state, when the object that is modified did not have a chance to escape between its creation and the store.
+
+Listing~\ref{lst:escape1} shows an example of a method that creates two \texttt{Point} objects, connects them, and returns them.
+The object allocation of the first \texttt{Point} object does not need a frame state.
+We can always reexecute the \texttt{NEW} bytecode again in the interpreter.
+The \texttt{Point} object allocated by the compiler will then simply disappear after the next garbage collection.
+The following field store is a thread-local memory store, because the \texttt{Point} object did not have any chance to escape.
+Same applies to the assignment of the \texttt{next} field and the third field assignment.
+Therefore, the whole method \texttt{getPoint} does not need an explicit frame state, because at any time during execution of this method, we can deoptimize and continue execution in the interpreter at the first bytecode of the method.
+
+\begin{lstlisting}[label=lst:escape1, caption=Example method that needs no frame state., captionpos=b]
+void getPoint() {
+  Point p = new Point();
+  p.x = 1;
+  p.next = new Point();
+  p.next.x = 2;
+  return p;
+}
+\end{lstlisting}
+
+The reduction of frame states makes it easier for the compiler to perform memory optimizations like memory access coalescing.
+We believe that this reduction on frame states is the key to effective vectorization and other compiler optimizations where compilers of compilers of unmanaged languages have advantages.
+
+\subsection{Guards}
+A guard is a node that deoptimizes based on a conditional expression.
+Guards are not attached to a certain frame state, they can move around freely and will always use the correct frame state when the nodes are scheduled (i.e., the last emitted frame state).
+The node that is guarded by the deoptimization has a data dependency on the guard and the guard in turn has a data dependency on the condition.
+A guard may only be executed if it is guaranteed that the guarded node is executed too (if no exceptions are thrown).
+Therefore, we use \texttt{Anchor} nodes after a control flow split and a data dependency from the guard to this anchor.
+The anchor is the most distant node that is postdominated by the guarded node and the guard can be scheduled anywhere between those two nodes.
+This ensures maximum flexibility for the guard node and guarantees that we only deoptimize if the control flow would have reached the guarded node (without taking exceptions into account).
+
+To illustrate the strengths of this approach, we show the graph for the Java code snippet shown in \ref{lst:guard1}.
+The example looks artificial, but in case of method inlining, this is a pattern that is not unlikely to be present in a normal Java program.
+Figure \ref{fig:guard0} shows the compiler graph for the example method after graph building.
+The field stores are both represented by a single node and the null check that is implicitely incorporated in the field store.
+
+\begin{lstlisting}[label=lst:guard1, caption=Example method that demonstrates the strengths of modelling the guards explicitely., captionpos=b]
+void init(Point p) {
+  if (p != null) {
+    p.x = 0;
+  }
+  p.y = 0;
+}
+\end{lstlisting}
+
+\begin{figure}[ht]
+  \centering
+\begin{digraphenv}{scale=0.5}{guard0}
+	\textnode{entry}{Entry}
+    \nodesplit{if}{If}
+    \node{merge}{Merge}
+    \node{return}{Return}
+    \node{cmpnull}{NonNull}
+    \textnode{p}{p}
+	\textnode{const0}{0}
+    \nodebisplit{store1}{FieldStore x}
+    \nodebisplit{store2}{FieldStore y}
+    \nodeframestate{fs1}{FrameState}
+    \nodeframestate{fs2}{FrameState}
+    \datalabel{store1:in1}{p}
+    \datalabel{store2:in1}{p}
+    \datalabel{store1:in2}{const0}
+    \datalabel{store2:in2}{const0}
+    \control{entry}{if}
+    \data{if}{cmpnull}
+    \controllabel{if:succ1}{merge}
+    \controllabel{if:succ2}{store1}
+    \controllabel{store1:succ1}{merge}
+    \controllabel{store1:succ2}{fs1}
+    \control{merge}{store2}
+    \controllabel{store2:succ1}{return}
+    \controllabel{store2:succ2}{fs2}
+    \data{cmpnull}{p}
+\end{digraphenv}
+  \caption{Initial graph with the two field stores.}
+  \label{fig:guard0}
+\end{figure}
+
+Figure~\ref{fig:guard1} shows the example graph at a later compilation phase when the field store nodes are lowered to memory store nodes and explicitely modelled null check guards.
+The guards are attached to anchor nodes that delimit their possible schedule.
+The first guard must not be moved outside the \texttt{if} block; the second guard may be moved before the \texttt{If} node, because at this point it is already guaranteed that the second store is executed.
+
+\begin{figure}[ht]
+  \centering
+\begin{digraphenv}{scale=0.5}{guard1}
+	\textnode{entry}{Entry}
+    \node{anchor1}{Anchor}
+    \node{anchor2}{Anchor}
+    \nodesplit{if}{If}
+    \node{merge}{Merge}
+    \node{return}{Return}
+    \node{cmpnull}{NonNull}
+    \textnode{p}{p}
+	\textnode{const0}{0}
+    \nodeguard{guard1}{Guard}
+    \nodeguard{guard2}{Guard}
+    \nodetrisplit{store1}{MemStore 16 (4 bytes)}
+    \nodetrisplit{store2}{MemStore 20 (4 bytes)}
+    \nodeframestate{fs1}{FrameState}
+    \nodeframestate{fs2}{FrameState}
+    \data{store1:in1}{p}
+    \data{store2:in1}{p}
+    \data{store1:in2}{const0}
+    \data{store2:in2}{const0}
+    \data{store1:in3}{guard1}
+    \data{store2:in3}{guard2}
+    \data{guard1:in1}{anchor2}
+    \data{guard2:in1}{anchor1}
+    \data{guard1:in2}{cmpnull}
+    \data{guard2:in2}{cmpnull}
+    \control{entry}{anchor1}
+    \control{anchor1}{if}
+    \data{if}{cmpnull}
+    \controllabel{if:succ1}{merge}
+    \controllabel{if:succ2}{anchor2}
+    \control{anchor2}{store1}
+    \controllabel{store1:succ1}{merge}
+    \controllabel{store1:succ2}{fs1}
+    \control{merge}{store2}
+    \controllabel{store2:succ1}{return}
+    \controllabel{store2:succ2}{fs2}
+    \data{cmpnull}{p}
+\end{digraphenv}
+  \caption{A load guarded by a null check guard.}
+  \label{fig:guard1}
+\end{figure}
+
+The first guard can be easily removed, because it is guarded by an \texttt{If} node that checks the same condition.
+Therefore we can remove the guard and the anchor from the graph and this gives us the graph shown in Figure \ref{fig:guard2}.
+
+There is another optimization for guard nodes: If two guards that are anchored to the true and false branch of the same \texttt{If} node have the same condition, they can be merged, so that the resulting guard is anchored at the most distant node of which the \texttt{If} node is a postdominator.
+
+
+\begin{figure}[ht]
+  \centering
+\begin{digraphenv}{scale=0.5}{guard2}
+	\textnode{entry}{Entry}
+    \node{anchor1}{Anchor}
+    \nodesplit{if}{If}
+    \node{merge}{Merge}
+    \node{return}{Return}
+    \node{cmpnull}{NonNull}
+    \textnode{p}{p}
+	\textnode{const0}{0}
+    \nodeguard{guard2}{Guard}
+    \nodetrisplit{store1}{MemStore 16 (4 bytes)}
+    \nodetrisplit{store2}{MemStore 20 (4 bytes)}
+    \nodeframestate{fs1}{FrameState}
+    \nodeframestate{fs2}{FrameState}
+    \data{store1:in1}{p}
+    \data{store2:in1}{p}
+    \data{store1:in2}{const0}
+    \data{store2:in2}{const0}
+    \data{store2:in3}{guard2}
+    \data{guard2:in1}{anchor1}
+    \data{guard2:in2}{cmpnull}
+    \control{entry}{anchor1}
+    \control{anchor1}{if}
+    \data{if}{cmpnull}
+    \controllabel{if:succ1}{merge}
+    \controllabel{if:succ2}{store1}
+    \controllabel{store1:succ1}{merge}
+    \controllabel{store1:succ2}{fs1}
+    \control{merge}{store2}
+    \controllabel{store2:succ1}{return}
+    \controllabel{store2:succ2}{fs2}
+    \data{cmpnull}{p}  
+\end{digraphenv}
+  \caption{After removing redundant guards.}
+  \label{fig:guard2}
+\end{figure}
+
+The remaining guard can now be moved above the \texttt{If} condition and be used to eliminate the need for the \texttt{If} node.
+From this point on, the guard can however no longer be moved below the first memory store.
+We use a control dependency from the guard to the field store to express this condition.
+The link between the second store and the guard and the control flow merge node is no longer necessary.
+
+\begin{figure}[ht]
+  \centering
+\begin{digraphenv}{scale=0.5}{guard3}
+	\textnode{entry}{Entry}
+    \node{anchor1}{Anchor}
+    \node{return}{Return}
+    \node{cmpnull}{NonNull}
+    \textnode{p}{p}
+	\textnode{const0}{0}
+    \nodeguard{guard2}{Guard}
+    \nodetrisplit{store1}{MemStore 16 (4 bytes)}
+    \nodetrisplit{store2}{MemStore 20 (4 bytes)}
+    \nodeframestate{fs1}{FrameState}
+    \nodeframestate{fs2}{FrameState}
+    \data{store1:in1}{p}
+    \data{store2:in1}{p}
+    \data{store1:in2}{const0}
+    \data{store2:in2}{const0}
+    \data{store2:in3}{guard2}
+    \data{guard2:in1}{anchor1}
+    \data{guard2:in2}{cmpnull}
+    \control{guard2}{store1}
+    \control{entry}{anchor1}
+    \control{anchor1}{store1}
+    \controllabel{store1:succ2}{fs1}
+    \control{store1}{store2}
+    \controllabel{store2:succ1}{return}
+    \controllabel{store2:succ2}{fs2}
+    \data{cmpnull}{p}  
+\end{digraphenv}
+  \caption{After eliminating an if with a guard.}
+  \label{fig:guard3}
+\end{figure}
+
+At some point during the compilation, guards need to be fixed, which means that appropriate data and control dependencies will be inserted so that they cannot move outside the scope of the associated frame state.
+This will generate deoptimization-free zones that can be targeted by the most aggressive optimizations.
+A simple algorithm for this removal of frame states would be to move all guards as far upwards as possible and then the guards are fixed using anchor nodes.
+In our example, the guard is already fixed, so there is no deoptimization point that uses any of the memory store frame states.
+Therefore we can delete the frame states from the graph (see Figure \ref{fig:guard4}).
+
+\begin{figure}[ht]
+  \centering
+\begin{digraphenv}{scale=0.5}{guard4}
+	\textnode{entry}{Entry}
+    \node{anchor1}{Anchor}
+    \node{return}{Return}
+    \node{cmpnull}{NonNull}
+    \textnode{p}{p}
+	\textnode{const0}{0}
+    \nodeguard{guard2}{Guard}
+    \nodetrisplit{store1}{MemStore 16 (4 bytes)}
+    \nodetrisplit{store2}{MemStore 20 (4 bytes)}
+    \data{store1:in1}{p}
+    \data{store2:in1}{p}
+    \data{store1:in2}{const0}
+    \data{store2:in2}{const0}
+    \data{store2:in3}{guard2}
+    \data{guard2:in1}{anchor1}
+    \data{guard2:in2}{cmpnull}
+    \control{guard2}{store1}
+    \control{entry}{anchor1}
+    \control{anchor1}{store1}
+    \control{store1}{store2}
+    \controllabel{store2:succ1}{return}
+    \data{cmpnull}{p}  
+\end{digraphenv}
+  \caption{After removing the frame states.}
+  \label{fig:guard4}
+\end{figure}
+
+Now we can use memory coalescing to combine the two stores without frame state to adjacent locations in the same object.
+This is only possible if the first store does not have a frame state.
+Figure \ref{fig:guard5} shows the resulting graph.
+
+
+\begin{figure}[ht]
+  \centering
+\begin{digraphenv}{scale=0.5}{guard5}
+	\textnode{entry}{Entry}
+    \node{anchor1}{Anchor}
+    \node{return}{Return}
+    \node{cmpnull}{NonNull}
+    \textnode{p}{p}
+	\textnode{const0}{0}
+    \nodeguard{guard2}{Guard}
+    \nodetrisplit{store1}{MemStore 16 (8 bytes)}
+    \data{store1:in1}{p}
+    \data{store1:in2}{const0}
+    \data{guard2:in1}{anchor1}
+    \data{guard2:in2}{cmpnull}
+    \control{guard2}{store1}
+    \control{entry}{anchor1}
+    \control{anchor1}{store1}
+    \controllabel{store1:succ1}{return}
+    \data{cmpnull}{p}  
+\end{digraphenv}
+  \caption{After coalescing the two memory stores.}
+  \label{fig:guard5}
+\end{figure}
+
+A memory store that immediately follows a null check guard node on the same object, can be combined into a store with an implicit null check (that deoptimizes instead of throwing the exception).
+Therefore, we can remove the guard again and also the anchor is no longer necessary.
+Figure~\ref{fig:guard6} shows now that fully optimized graph that is generated for Listing~\ref{lst:guard1}.
+
+\begin{figure}[ht]
+  \centering
+\begin{digraphenv}{scale=0.5}{guard6} 
+	\textnode{entry}{Entry}
+    \node{return}{Return}
+    \textnode{p}{p}
+	\textnode{const0}{0}
+    \nodetrisplit{store1}{DeoptimizingMemStore 16 (8 bytes)}
+    \data{store1:in1}{p}
+    \data{store1:in2}{const0}
+    \control{entry}{store1}
+    \controllabel{store1:succ1}{return}
+\end{digraphenv}
+  \caption{Fully optimized method.}
+  \label{fig:guard6}
+\end{figure}
+
+
+\section{Conclusions}
+\label{sec:conclusions}
+This document sketched the strategy for the Graph compiler.
+We have the following plans for M1 to M4:
+\begin{description}
+\item[M1:] May 15th, 2011
+\item[M2:] June 30th, 2011
+\item[M3:] August 15th, 2011
+\item[M4:] September 30th, 2011
+\end{description}
+After we reach M4, we want to create a new project road map that further improves the Graal compiler with respect to its two main goals: Modularity and peak performance.
+
+\end{document}
Binary file graal/com.oracle.max.graal.doc.initial/graph_test.pdf has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.doc.initial/graph_test.tex	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,160 @@
+\documentclass[twocolumn]{svjour3}
+\usepackage[pdftex]{graphicx}
+\usepackage{environ}
+\usepackage{amsmath}
+\usepackage{amsfonts}
+\usepackage[english]{babel}
+\usepackage[utf8]{inputenc} 
+\usepackage{lmodern}
+\usepackage[T1]{fontenc}
+\usepackage{color}
+
+\input{graphdrawing}
+
+\renewcommand*\descriptionlabel[1]{\hspace\labelsep\normalfont\bf #1}
+
+\newcommand{\Sa}{{\Large$^*$}}
+\newcommand{\Sb}{{\Large$^\dag$}}
+\newcommand{\Sc}{{\Large$^\S$}}
+
+\smartqed  % flush right qed marks, e.g. at end of proof
+
+\journalname{Test}
+\def\makeheadbox{{%
+\hbox to0pt{\vbox{\baselineskip=10dd\hrule\hbox
+to\hsize{\vrule\kern3pt\vbox{\kern3pt
+\hbox{\bfseries Test}
+\kern3pt}\hfil\kern3pt\vrule}\hrule}%
+\hss}}}
+
+\begin{document}
+
+\author{}
+\institute{}
+
+\date{Created: \today}
+
+\title{Test}
+\subtitle{}
+
+\maketitle
+
+\begin{digraphenv}{scale=0.5}{layout1}
+    \nodestart
+    \nodeend
+    \data{a}{start}
+    \data{b}{start}
+    \node{a}{a}
+    \node{b}{b}
+    \nodesplit{if}{if}
+    \node{nop}{nop}
+    \nodebi{add}{+}
+    \controllabel{if:succ1}{nop}
+    \controllabel{if:succ2}{add}
+    \datalabel{add:in1}{a}
+    \datalabel{add:in2}{b}
+    \control{nop}{end}
+\end{digraphenv}
+
+\begin{digraphenv}{scale=0.5}{layout2}
+    \node{node1}{nop}
+    \nodebi{node2}{+}
+    \nodetri{node3}{phi}
+    \nodesplit{node4}{if}
+\end{digraphenv}
+
+\begin{digraphenv}{scale=0.5}{layout3}
+    \node{a}{a}
+    \node{b}{b}
+    \nodesplit{if}{if}
+    \node{nop}{nop}
+    \nodebi{add}{+}
+    \controllabel{if:succ1}{nop}
+    \controllabel{if:succ2}{add}
+    \datalabel{add:in1}{a}
+    \datalabel{add:in2}{b}
+\end{digraphenv}
+
+\begin{digraphenv}{scale=0.5}{layout4}
+    \node{arr}{arr}
+    \node{i}{i}
+    \node{j}{j}
+    \node{v}{v}
+    \nodetri{astore1}{astore}
+    \datalabel{astore1:in1}{arr}
+    \datalabel{astore1:in2}{i}
+    \datalabel{astore1:in3}{v}
+    \nodebi{add}{+}
+    \datalabel{add:in1}{i}
+    \datalabel{add:in2}{j}
+    \nodetri{astore2}{astore}
+    \datalabel{astore2:in1}{arr}
+    \datalabel{astore2:in2}{add}
+    \datalabel{astore2:in3}{v}
+    \cnode{fs}{framestate}{lightblue}
+    \control{fs}{astore2}
+    \data{fs}{astore1}
+%    \data{fs}{arr}
+%    \data{fs}{i}
+%    \data{fs}{j}
+%    \data{fs}{v}
+    \control{astore1}{astore2}
+\end{digraphenv}
+
+\begin{digraphenv}{scale=0.5}{layout5}
+    \nodestart
+    \nodeend
+    % input projections
+    \node{a}{proj:a}
+    \node{b}{proj:b}
+    \data{a}{start}
+    \data{b}{start}
+    % if
+    \nodebi{cmp1}{&lt;}
+    \datalabel{cmp1:in1}{a}
+    \datalabel{cmp1:in2}{b}
+    \nodesplit{if}{if}
+    \data{if}{cmp1}
+    \control{start}{if}
+    % branches
+    \nodebi{add1}{+}
+    \datalabel{add1:in1}{a}
+    \datalabel{add1:in2}{b}
+    \nodebi{sub1}{-}
+    \datalabel{sub1:in1}{a}
+    \datalabel{sub1:in2}{b}
+    \controllabel{if:succ1}{add1}
+    \controllabel{if:succ2}{sub1}
+    % merge
+    \nodebi{merge}{merge}
+    \control{add1}{merge}
+    \control{sub1}{merge}
+    % phi
+    \nodebi{phi1}{phi}
+    \datalabel{phi1:in1}{add1}
+    \datalabel{phi1:in2}{sub1}
+    % ret
+    \node{ret}{ret}
+    \data{ret}{phi1}
+    \control{merge}{ret}
+    \control{ret}{end}
+\end{digraphenv}
+
+\end{document}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.doc.initial/graphdrawing.tex	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,109 @@
+
+% graph drawing
+\newwrite\dotfile 
+\newcommand{\digraph}[3][scale=1]{ 
+  \immediate\openout\dotfile=dot_temp_#2.dot 
+  \immediate\write\dotfile{digraph #2 { margin=0; pad=0; concentrate=false; \string#3}} 
+  \immediate\closeout\dotfile
+  \immediate\write18{bash -c "dot -Tpdf dot_temp_#2.dot > dot_temp_#2.pdf"}  
+  \IfFileExists{dot_temp_#2.pdf}
+  % the pdf exists: include it 
+  { \includegraphics[#1]{dot_temp_#2} } 
+  % the pdf was not created - show a hint
+  { \fbox{ \begin{tabular}{l} 
+        The file \texttt{dot_temp_#2.pdf} hasn't been created from 
+        \texttt{dot_temp_#2.dot} yet. \\
+        We attempted to create it with:\\
+        `\texttt{dot -Tpdf dot_temp_#2.dot > dot_temp_#2.pdf}' \\
+        but that seems not to have worked. You need to execute `\texttt{pdflatex}' with \\
+        the `\texttt{-shell-escape} option.
+      \end{tabular}} 
+  } 
+}
+
+\NewEnviron{digraphenv}[2]{\digraph[#1]{#2}{ nodesep="0.1"; ranksep="0.08 equally"; \BODY }}
+
+\newcommand{\control}[2]{#1:successors:s -> #2:predecessors:n [color=red,style=solid];}
+\newcommand{\controllabel}[2]{#1:s -> #2:predecessors:n [color=red,style=solid];}
+\newcommand{\data}[2]{#2:usages:s -> #1:inputs [color=black,dir=back];}
+\newcommand{\datalabel}[2]{#2:usages:s -> #1:n [color=black,dir=back];}
+\newcommand{\datalabeltext}[3]{#2:usages:s -> #1:n [color=black,dir=back,label="#3"];}
+
+\newcommand{\textnode}[2]{#1 [shape=plaintext, label="#2"]}
+\newcommand{\genericnodestart}[1]{#1 [shape=plaintext, label=< <TABLE BORDER="0" CELLSPACING="0"><TR><TD CELLPADDING="0"><TABLE BORDER="0" CELLSPACING="2" CELLPADDING="0"><TR><TD WIDTH="15" HEIGHT="5" PORT="predecessors" BGCOLOR="rosybrown1"></TD></TR></TABLE></TD><TD COLSPAN="2" CELLPADDING="0" ALIGN="RIGHT"><TABLE BORDER="0" CELLSPACING="2" CELLPADDING="0"><TR>}
+\newcommand{\genericnodeend}[0]{</TR></TABLE></TD><TD CELLPADDING="0"><TABLE BORDER="0" CELLSPACING="2" CELLPADDING="0"><TR><TD WIDTH="15" HEIGHT="5" PORT="usages" BGCOLOR="lightgrey"></TD></TR></TABLE></TD></TR></TABLE>>]}
+\newcommand{\portinput}[1]{<TD WIDTH="15" HEIGHT="5" PORT="#1" BGCOLOR="lightgrey"></TD>}
+\newcommand{\portsuccessor}[1]{<TD WIDTH="15" HEIGHT="5" PORT="#1" BGCOLOR="rosybrown1"></TD>}
+\newcommand{\portempty}[0]{<TD WIDTH="15" HEIGHT="5"></TD>}
+\newcommand{\genericnodelabel}[2]{</TR></TABLE></TD></TR><TR><TD BORDER="1" COLSPAN="3" BGCOLOR="#2"><FONT POINT-SIZE="12">#1</FONT></TD></TR><TR><TD COLSPAN="2" CELLPADDING="0" ALIGN="RIGHT"><TABLE BORDER="0" CELLSPACING="2" CELLPADDING="0"><TR>}
+
+\newcommand{\nodestart}[0]{start [shape=plaintext, rank=source, label=< <TABLE BORDER="0" CELLSPACING="0"><TR><TD COLSPAN="3"><TABLE BORDER="0"><TR><TD></TD> \genericnodelabel{start}{lightyellow} \portsuccessor{successors} \portempty \genericnodeend }
+
+\newcommand{\nodeend}[0]{\genericnodestart{end} \portempty \portinput{inputs} \genericnodelabel{end}{lightyellow} <TD></TD></TR></TABLE></TD><TD></TD></TR></TABLE>>]}
+
+\newcommand{\nodeconst}[2]{#1 [margin="0.05, 0.05", shape=plaintext, label=< <TABLE BORDER="0" CELLSPACING="0"><TR><TD BORDER="1" BGCOLOR="white"><FONT POINT-SIZE="12">#2</FONT></TD></TR><TR><TD WIDTH="15" HEIGHT="5" PORT="usages" BGCOLOR="lightgrey"></TD></TR></TABLE>>]}
+\newcommand{\nodeframestate}[2]{#1 [margin="0.05, 0.05", shape=plaintext, label=< <TABLE BORDER="0" CELLSPACING="0"><TR><TD WIDTH="15" HEIGHT="5" PORT="predecessors" BGCOLOR="rosybrown1"></TD><TD WIDTH="15" HEIGHT="5"></TD><TD HEIGHT="5" PORT="inputs" BGCOLOR="lightgrey"></TD></TR><TR><TD BORDER="1" COLSPAN="3" BGCOLOR="lightblue"><FONT POINT-SIZE="12">#2</FONT></TD></TR></TABLE>>]}
+
+
+\newcommand{\node}[2]{\genericnodestart{#1} \portempty \portinput{inputs} \genericnodelabel{#2}{white} \portsuccessor{successors} \portempty \genericnodeend }
+\newcommand{\nodebi}[2]{\genericnodestart{#1} \portinput{in1} \portinput{in2} \genericnodelabel{#2}{white} \portsuccessor{successors} \portempty \genericnodeend }
+\newcommand{\nodetri}[2]{\genericnodestart{#1} \portinput{in1} \portinput{in2} \portinput{in3} \genericnodelabel{#2}{white} \portsuccessor{successors} \portempty \portempty \genericnodeend }
+\newcommand{\nodequad}[2]{\genericnodestart{#1} \portinput{in1} \portinput{in2} \portinput{in3} \portinput{in4} \genericnodelabel{#2}{white} \portsuccessor{successors} \portempty \portempty \portempty \genericnodeend }
+\newcommand{\nodesplit}[2]{\genericnodestart{#1} \portempty \portinput{inputs} \genericnodelabel{#2}{white} \portsuccessor{succ1} \portsuccessor{succ2} \genericnodeend }
+\newcommand{\nodequadsplit}[2]{\genericnodestart{#1} \portinput{in1} \portinput{in2} \portinput{in3} \portinput{in4} \genericnodelabel{#2}{white} \portsuccessor{succ1} \portsuccessor{succ2} \portempty \portempty \genericnodeend }
+\newcommand{\nodetrisplit}[2]{\genericnodestart{#1} \portinput{in1} \portinput{in2} \portinput{in3} \genericnodelabel{#2}{white} \portsuccessor{succ1} \portsuccessor{succ2} \portempty \genericnodeend }
+\newcommand{\nodesplittri}[2]{\genericnodestart{#1} \portempty \portinput{inputs} \genericnodelabel{#2}{white} \portsuccessor{succ1} \portsuccessor{succ2} \portsuccessor{succ3} \genericnodeend }
+\newcommand{\nodebisplit}[2]{\genericnodestart{#1} \portinput{in1} \portinput{in2} \genericnodelabel{#2}{white} \portsuccessor{succ1} \portsuccessor{succ2} \portempty \genericnodeend }
+
+\newcommand{\nodeguard}[2]{\cnodebi{#1}{#2}{rosybrown1}}
+
+\newcommand{\cnode}[3]{\genericnodestart{#1} \portempty \portinput{inputs} \genericnodelabel{#2}{#3} \portsuccessor{successors} \portempty \genericnodeend }
+\newcommand{\cnodebi}[3]{\genericnodestart{#1} \portinput{in1} \portinput{in2} \genericnodelabel{#2}{#3} \portsuccessor{successors} \portempty \genericnodeend }
+\newcommand{\cnodetri}[3]{\genericnodestart{#1} \portinput{in1} \portinput{in2} \portinput{in3} \genericnodelabel{#2}{#3} \portsuccessor{successors} \portempty \portempty \genericnodeend }
+\newcommand{\cnodesplit}[3]{\genericnodestart{#1} \portempty \portinput{inputs} \genericnodelabel{#2}{#3} \portsuccessor{succ1} \portsuccessor{succ2} \genericnodeend }
+
+% this doesn't work:
+%\newenvironment{graphfigure}[2]{\begin{figure}[h] \label{fig:#1} \centering \begin{digraphenv}{scale=0.5}{#1}}{\end{digraphenv} \caption{#2} \end{figure}}
+
+%%%%%%%%%%%%%% example:
+
+% \begin{digraphenv}{scale=0.5}{MyGraph}
+% \node{start}{start}
+% \node{end}{end}
+% % input projections
+% \node{a}{proj:a}
+% \node{b}{proj:b}
+% \data{a}{start}
+% \data{b}{start}
+% % if
+% \nodebi{cmp1}{&lt;}
+% \datalabel{cmp1:in1}{a}
+% \datalabel{cmp1:in2}{b}
+% \nodesplit{if}{if}
+% \data{if}{cmp1}
+% \control{start}{if}
+% % branches
+% \nodebi{add1}{+}
+% \datalabel{add1:in1}{a}
+% \datalabel{add1:in2}{b}
+% \nodebi{sub1}{-}
+% \datalabel{sub1:in1}{a}
+% \datalabel{sub1:in2}{b}
+% \controllabel{if:succ1}{add1}
+% \controllabel{if:succ2}{sub1}
+% % merge
+% \nodebi{merge}{merge}
+% \control{add1}{merge}
+% \control{sub1}{merge}
+% % phi
+% \nodebi{phi1}{phi}
+% \datalabel{phi1:in1}{add1}
+% \datalabel{phi1:in2}{sub1}
+% % ret
+% \node{ret}{ret}
+% \data{ret}{phi1}
+% \control{merge}{ret}
+% \control{ret}{end}
+% \end{digraphenv}
+
+%%%%%%%%%%%%%%%
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.doc.initial/svglov3.clo	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,101 @@
+% SVJour3 DOCUMENT CLASS OPTION SVGLOV3 -- for standardised journals
+%
+% This is an enhancement for the LaTeX
+% SVJour3 document class for Springer journals
+%
+%%
+%%
+%% \CharacterTable
+%%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%%   Digits        \0\1\2\3\4\5\6\7\8\9
+%%   Exclamation   \!     Double quote  \"     Hash (number) \#
+%%   Dollar        \$     Percent       \%     Ampersand     \&
+%%   Acute accent  \'     Left paren    \(     Right paren   \)
+%%   Asterisk      \*     Plus          \+     Comma         \,
+%%   Minus         \-     Point         \.     Solidus       \/
+%%   Colon         \:     Semicolon     \;     Less than     \<
+%%   Equals        \=     Greater than  \>     Question mark \?
+%%   Commercial at \@     Left bracket  \[     Backslash     \\
+%%   Right bracket \]     Circumflex    \^     Underscore    \_
+%%   Grave accent  \`     Left brace    \{     Vertical bar  \|
+%%   Right brace   \}     Tilde         \~}
+\ProvidesFile{svglov3.clo}
+              [2006/02/03 v3.1
+      style option for standardised journals]
+\typeout{SVJour Class option: svglov3.clo for standardised journals}
+\def\validfor{svjour3}
+\ExecuteOptions{final,10pt,runningheads}
+% No size changing allowed, hence a "copy" of size10.clo is included
+\renewcommand\normalsize{%
+\if@twocolumn
+   \@setfontsize\normalsize\@xpt{12.5pt}%
+\else
+   \if@smallext
+      \@setfontsize\normalsize\@xpt\@xiipt
+   \else
+      \@setfontsize\normalsize{9.5pt}{11.5pt}%
+   \fi
+\fi
+   \abovedisplayskip=3 mm plus6pt minus 4pt
+   \belowdisplayskip=3 mm plus6pt minus 4pt
+   \abovedisplayshortskip=0.0 mm plus6pt
+   \belowdisplayshortskip=2 mm plus4pt minus 4pt
+   \let\@listi\@listI}
+\normalsize
+\newcommand\small{%
+\if@twocolumn
+   \@setfontsize\small{8.5pt}\@xpt
+\else
+   \if@smallext
+      \@setfontsize\small\@viiipt{9.5pt}%
+   \else
+      \@setfontsize\small\@viiipt{9.25pt}%
+   \fi
+\fi
+   \abovedisplayskip 8.5\p@ \@plus3\p@ \@minus4\p@
+   \abovedisplayshortskip \z@ \@plus2\p@
+   \belowdisplayshortskip 4\p@ \@plus2\p@ \@minus2\p@
+   \def\@listi{\leftmargin\leftmargini
+               \parsep 0\p@ \@plus1\p@ \@minus\p@
+               \topsep 4\p@ \@plus2\p@ \@minus4\p@
+               \itemsep0\p@}%
+   \belowdisplayskip \abovedisplayskip
+}
+\let\footnotesize\small
+\newcommand\scriptsize{\@setfontsize\scriptsize\@viipt\@viiipt}
+\newcommand\tiny{\@setfontsize\tiny\@vpt\@vipt}
+\if@twocolumn
+   \newcommand\large{\@setfontsize\large\@xiipt\@xivpt}
+   \newcommand\LARGE{\@setfontsize\LARGE{16pt}{18pt}}
+\else
+   \newcommand\large{\@setfontsize\large\@xipt\@xiipt}
+   \newcommand\LARGE{\@setfontsize\LARGE{13pt}{15pt}}
+\fi
+\newcommand\Large{\@setfontsize\Large\@xivpt{16dd}}
+\newcommand\huge{\@setfontsize\huge\@xxpt{25}}
+\newcommand\Huge{\@setfontsize\Huge\@xxvpt{30}}
+%
+\def\runheadhook{\rlap{\smash{\lower6.5pt\hbox to\textwidth{\hrulefill}}}}
+\if@twocolumn
+\setlength{\textwidth}{17.4cm}
+\setlength{\textheight}{234mm}
+\AtEndOfClass{\setlength\columnsep{6mm}}
+\else
+   \if@smallext
+      \setlength{\textwidth}{11.9cm}
+      \setlength{\textheight}{19.4cm}
+   \else
+      \setlength{\textwidth}{12.2cm}
+      \setlength{\textheight}{19.8cm}
+   \fi
+\fi
+%
+\AtBeginDocument{%
+\@ifundefined{@journalname}
+ {\typeout{Unknown journal: specify \string\journalname\string{%
+<name of your journal>\string} in preambel^^J}}{}}
+%
+\endinput
+%%
+%% End of file `svglov3.clo'.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.doc.initial/svjour3.cls	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,1431 @@
+% SVJour3 DOCUMENT CLASS -- version 3.2 for LaTeX2e
+%
+% LaTeX document class for Springer journals
+%
+%%
+%%
+%% \CharacterTable
+%%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%%   Digits        \0\1\2\3\4\5\6\7\8\9
+%%   Exclamation   \!     Double quote  \"     Hash (number) \#
+%%   Dollar        \$     Percent       \%     Ampersand     \&
+%%   Acute accent  \'     Left paren    \(     Right paren   \)
+%%   Asterisk      \*     Plus          \+     Comma         \,
+%%   Minus         \-     Point         \.     Solidus       \/
+%%   Colon         \:     Semicolon     \;     Less than     \<
+%%   Equals        \=     Greater than  \>     Question mark \?
+%%   Commercial at \@     Left bracket  \[     Backslash     \\
+%%   Right bracket \]     Circumflex    \^     Underscore    \_
+%%   Grave accent  \`     Left brace    \{     Vertical bar  \|
+%%   Right brace   \}     Tilde         \~}
+\NeedsTeXFormat{LaTeX2e}[1995/12/01]
+\ProvidesClass{svjour3}[2007/05/08 v3.2
+^^JLaTeX document class for Springer journals]
+\newcommand\@ptsize{}
+\newif\if@restonecol
+\newif\if@titlepage
+\@titlepagefalse
+\DeclareOption{a4paper}
+   {\setlength\paperheight {297mm}%
+    \setlength\paperwidth  {210mm}}
+\DeclareOption{10pt}{\renewcommand\@ptsize{0}}
+\DeclareOption{twoside}{\@twosidetrue  \@mparswitchtrue}
+\DeclareOption{draft}{\setlength\overfullrule{5pt}}
+\DeclareOption{final}{\setlength\overfullrule{0pt}}
+\DeclareOption{fleqn}{\input{fleqn.clo}\AtBeginDocument{\mathindent\z@}%
+\AtBeginDocument{\@ifpackageloaded{amsmath}{\@mathmargin\z@}{}}%
+\PassOptionsToPackage{fleqn}{amsmath}}
+%%%
+\DeclareOption{onecolumn}{}
+\DeclareOption{smallcondensed}{}
+\DeclareOption{twocolumn}{\@twocolumntrue\ExecuteOptions{fleqn}}
+\newif\if@smallext\@smallextfalse
+\DeclareOption{smallextended}{\@smallexttrue}
+\let\if@mathematic\iftrue
+\let\if@numbook\iffalse
+\DeclareOption{numbook}{\let\if@envcntsect\iftrue
+  \AtEndOfPackage{%
+   \renewcommand\thefigure{\thesection.\@arabic\c@figure}%
+   \renewcommand\thetable{\thesection.\@arabic\c@table}%
+   \renewcommand\theequation{\thesection.\@arabic\c@equation}%
+   \@addtoreset{figure}{section}%
+   \@addtoreset{table}{section}%
+   \@addtoreset{equation}{section}%
+  }%
+}
+\DeclareOption{openbib}{%
+  \AtEndOfPackage{%
+   \renewcommand\@openbib@code{%
+      \advance\leftmargin\bibindent
+      \itemindent -\bibindent
+      \listparindent \itemindent
+      \parsep \z@
+      }%
+   \renewcommand\newblock{\par}}%
+}
+\DeclareOption{natbib}{%
+\AtEndOfClass{\RequirePackage{natbib}%
+% Changing some parameters of NATBIB
+\setlength{\bibhang}{\parindent}%
+%\setlength{\bibsep}{0mm}%
+\let\bibfont=\small
+\def\@biblabel#1{#1.}%
+\newcommand{\etal}{et al.}%
+\bibpunct{(}{)}{;}{a}{}{,}}}
+%
+\let\if@runhead\iffalse
+\DeclareOption{runningheads}{\let\if@runhead\iftrue}
+\let\if@smartrunh\iffalse
+\DeclareOption{smartrunhead}{\let\if@smartrunh\iftrue}
+\DeclareOption{nosmartrunhead}{\let\if@smartrunh\iffalse}
+\let\if@envcntreset\iffalse
+\DeclareOption{envcountreset}{\let\if@envcntreset\iftrue}
+\let\if@envcntsame\iffalse
+\DeclareOption{envcountsame}{\let\if@envcntsame\iftrue}
+\let\if@envcntsect\iffalse
+\DeclareOption{envcountsect}{\let\if@envcntsect\iftrue}
+\let\if@referee\iffalse
+\DeclareOption{referee}{\let\if@referee\iftrue}
+\def\makereferee{\def\baselinestretch{2}}
+\let\if@instindent\iffalse
+\DeclareOption{instindent}{\let\if@instindent\iftrue}
+\let\if@smartand\iffalse
+\DeclareOption{smartand}{\let\if@smartand\iftrue}
+\let\if@spthms\iftrue
+\DeclareOption{nospthms}{\let\if@spthms\iffalse}
+%
+% language and babel dependencies
+\DeclareOption{deutsch}{\def\switcht@@therlang{\switcht@deutsch}%
+\gdef\svlanginfo{\typeout{Man spricht deutsch.}\global\let\svlanginfo\relax}}
+\DeclareOption{francais}{\def\switcht@@therlang{\switcht@francais}%
+\gdef\svlanginfo{\typeout{On parle francais.}\global\let\svlanginfo\relax}}
+\let\switcht@@therlang\relax
+\let\svlanginfo\relax
+%
+\AtBeginDocument{\@ifpackageloaded{babel}{%
+\@ifundefined{extrasenglish}{}{\addto\extrasenglish{\switcht@albion}}%
+\@ifundefined{extrasUKenglish}{}{\addto\extrasUKenglish{\switcht@albion}}%
+\@ifundefined{extrasfrenchb}{}{\addto\extrasfrenchb{\switcht@francais}}%
+\@ifundefined{extrasgerman}{}{\addto\extrasgerman{\switcht@deutsch}}%
+\@ifundefined{extrasngerman}{}{\addto\extrasngerman{\switcht@deutsch}}%
+}{\switcht@@therlang}%
+}
+%
+\def\ClassInfoNoLine#1#2{%
+   \ClassInfo{#1}{#2\@gobble}%
+}
+\let\journalopt\@empty
+\DeclareOption*{%
+\InputIfFileExists{sv\CurrentOption.clo}{%
+\global\let\journalopt\CurrentOption}{%
+\ClassWarning{Springer-SVJour3}{Specified option or subpackage
+"\CurrentOption" not found -}\OptionNotUsed}}
+\ExecuteOptions{a4paper,twoside,10pt,instindent}
+\ProcessOptions
+%
+\ifx\journalopt\@empty\relax
+\ClassInfoNoLine{Springer-SVJour3}{extra/valid Springer sub-package (-> *.clo)
+\MessageBreak not found in option list of \string\documentclass
+\MessageBreak  - autoactivating "global" style}{}
+\input{svglov3.clo}
+\else
+\@ifundefined{validfor}{%
+\ClassError{Springer-SVJour3}{Possible option clash for sub-package
+\MessageBreak "sv\journalopt.clo" - option file not valid
+\MessageBreak for this class}{Perhaps you used an option of the old
+Springer class SVJour!}
+}{}
+\fi
+%
+\if@smartrunh\AtEndDocument{\islastpageeven\getlastpagenumber}\fi
+%
+\newcommand{\twocoltest}[2]{\if@twocolumn\def\@gtempa{#2}\else\def\@gtempa{#1}\fi
+\@gtempa\makeatother}
+\newcommand{\columncase}{\makeatletter\twocoltest}
+%
+\DeclareMathSymbol{\Gamma}{\mathalpha}{letters}{"00}
+\DeclareMathSymbol{\Delta}{\mathalpha}{letters}{"01}
+\DeclareMathSymbol{\Theta}{\mathalpha}{letters}{"02}
+\DeclareMathSymbol{\Lambda}{\mathalpha}{letters}{"03}
+\DeclareMathSymbol{\Xi}{\mathalpha}{letters}{"04}
+\DeclareMathSymbol{\Pi}{\mathalpha}{letters}{"05}
+\DeclareMathSymbol{\Sigma}{\mathalpha}{letters}{"06}
+\DeclareMathSymbol{\Upsilon}{\mathalpha}{letters}{"07}
+\DeclareMathSymbol{\Phi}{\mathalpha}{letters}{"08}
+\DeclareMathSymbol{\Psi}{\mathalpha}{letters}{"09}
+\DeclareMathSymbol{\Omega}{\mathalpha}{letters}{"0A}
+%
+\setlength\parindent{15\p@}
+\setlength\smallskipamount{3\p@ \@plus 1\p@ \@minus 1\p@}
+\setlength\medskipamount{6\p@ \@plus 2\p@ \@minus 2\p@}
+\setlength\bigskipamount{12\p@ \@plus 4\p@ \@minus 4\p@}
+\setlength\headheight{12\p@}
+\setlength\headsep   {14.50dd}
+\setlength\topskip   {10\p@}
+\setlength\footskip{30\p@}
+\setlength\maxdepth{.5\topskip}
+%
+\@settopoint\textwidth
+\setlength\marginparsep {10\p@}
+\setlength\marginparpush{5\p@}
+\setlength\topmargin{-10pt}
+\if@twocolumn
+   \setlength\oddsidemargin {-30\p@}
+   \setlength\evensidemargin{-30\p@}
+\else
+   \setlength\oddsidemargin {\z@}
+   \setlength\evensidemargin{\z@}
+\fi
+\setlength\marginparwidth  {48\p@}
+\setlength\footnotesep{8\p@}
+\setlength{\skip\footins}{9\p@ \@plus 4\p@ \@minus 2\p@}
+\setlength\floatsep    {12\p@ \@plus 2\p@ \@minus 2\p@}
+\setlength\textfloatsep{20\p@ \@plus 2\p@ \@minus 4\p@}
+\setlength\intextsep   {20\p@ \@plus 2\p@ \@minus 2\p@}
+\setlength\dblfloatsep    {12\p@ \@plus 2\p@ \@minus 2\p@}
+\setlength\dbltextfloatsep{20\p@ \@plus 2\p@ \@minus 4\p@}
+\setlength\@fptop{0\p@}
+\setlength\@fpsep{12\p@ \@plus 2\p@ \@minus 2\p@}
+\setlength\@fpbot{0\p@ \@plus 1fil}
+\setlength\@dblfptop{0\p@}
+\setlength\@dblfpsep{12\p@ \@plus 2\p@ \@minus 2\p@}
+\setlength\@dblfpbot{0\p@ \@plus 1fil}
+\setlength\partopsep{2\p@ \@plus 1\p@ \@minus 1\p@}
+\def\@listi{\leftmargin\leftmargini
+            \parsep \z@
+            \topsep 6\p@ \@plus2\p@ \@minus4\p@
+            \itemsep\parsep}
+\let\@listI\@listi
+\@listi
+\def\@listii {\leftmargin\leftmarginii
+              \labelwidth\leftmarginii
+              \advance\labelwidth-\labelsep
+              \topsep    \z@
+              \parsep    \topsep
+              \itemsep   \parsep}
+\def\@listiii{\leftmargin\leftmarginiii
+              \labelwidth\leftmarginiii
+              \advance\labelwidth-\labelsep
+              \topsep    \z@
+              \parsep    \topsep
+              \itemsep   \parsep}
+\def\@listiv {\leftmargin\leftmarginiv
+              \labelwidth\leftmarginiv
+              \advance\labelwidth-\labelsep}
+\def\@listv  {\leftmargin\leftmarginv
+              \labelwidth\leftmarginv
+              \advance\labelwidth-\labelsep}
+\def\@listvi {\leftmargin\leftmarginvi
+              \labelwidth\leftmarginvi
+              \advance\labelwidth-\labelsep}
+%
+\setlength\lineskip{1\p@}
+\setlength\normallineskip{1\p@}
+\renewcommand\baselinestretch{}
+\setlength\parskip{0\p@ \@plus \p@}
+\@lowpenalty   51
+\@medpenalty  151
+\@highpenalty 301
+\setcounter{topnumber}{4}
+\renewcommand\topfraction{.9}
+\setcounter{bottomnumber}{2}
+\renewcommand\bottomfraction{.7}
+\setcounter{totalnumber}{6}
+\renewcommand\textfraction{.1}
+\renewcommand\floatpagefraction{.85}
+\setcounter{dbltopnumber}{3}
+\renewcommand\dbltopfraction{.85}
+\renewcommand\dblfloatpagefraction{.85}
+\def\ps@headings{%
+    \let\@oddfoot\@empty\let\@evenfoot\@empty
+    \def\@evenhead{\small\csname runheadhook\endcsname
+    \rlap{\thepage}\hfil\leftmark\unskip}%
+    \def\@oddhead{\small\csname runheadhook\endcsname
+    \ignorespaces\rightmark\hfil\llap{\thepage}}%
+    \let\@mkboth\@gobbletwo
+    \let\sectionmark\@gobble
+    \let\subsectionmark\@gobble
+    }
+% make indentations changeable
+\def\setitemindent#1{\settowidth{\labelwidth}{#1}%
+        \leftmargini\labelwidth
+        \advance\leftmargini\labelsep
+   \def\@listi{\leftmargin\leftmargini
+        \labelwidth\leftmargini\advance\labelwidth by -\labelsep
+        \parsep=\parskip
+        \topsep=\medskipamount
+        \itemsep=\parskip \advance\itemsep by -\parsep}}
+\def\setitemitemindent#1{\settowidth{\labelwidth}{#1}%
+        \leftmarginii\labelwidth
+        \advance\leftmarginii\labelsep
+\def\@listii{\leftmargin\leftmarginii
+        \labelwidth\leftmarginii\advance\labelwidth by -\labelsep
+        \parsep=\parskip
+        \topsep=\z@
+        \itemsep=\parskip \advance\itemsep by -\parsep}}
+% labels of description
+\def\descriptionlabel#1{\hspace\labelsep #1\hfil}
+% adjusted environment "description"
+% if an optional parameter (at the first two levels of lists)
+% is present, its width is considered to be the widest mark
+% throughout the current list.
+\def\description{\@ifnextchar[{\@describe}{\list{}{\labelwidth\z@
+          \itemindent-\leftmargin \let\makelabel\descriptionlabel}}}
+\let\enddescription\endlist
+%
+\def\describelabel#1{#1\hfil}
+\def\@describe[#1]{\relax\ifnum\@listdepth=0
+\setitemindent{#1}\else\ifnum\@listdepth=1
+\setitemitemindent{#1}\fi\fi
+\list{--}{\let\makelabel\describelabel}}
+%
+\newdimen\logodepth
+\logodepth=1.2cm
+\newdimen\headerboxheight
+\headerboxheight=163pt % 18 10.5dd-lines - 2\baselineskip
+\if@twocolumn\else\advance\headerboxheight by-14.5mm\fi
+\newdimen\betweenumberspace          % dimension for space between
+\betweenumberspace=3.33pt            % number and text of titles.
+\newdimen\aftertext                  % dimension for space after
+\aftertext=5pt                       % text of title.
+\newdimen\headlineindent             % dimension for space between
+\headlineindent=1.166cm              % number and text of headings.
+\if@mathematic
+   \def\runinend{} % \enspace}
+   \def\floatcounterend{\enspace}
+   \def\sectcounterend{}
+\else
+   \def\runinend{.}
+   \def\floatcounterend{.\ }
+   \def\sectcounterend{.}
+\fi
+\def\email#1{\emailname: #1}
+\def\keywords#1{\par\addvspace\medskipamount{\rightskip=0pt plus1cm
+\def\and{\ifhmode\unskip\nobreak\fi\ $\cdot$
+}\noindent\keywordname\enspace\ignorespaces#1\par}}
+%
+\def\subclassname{{\bfseries Mathematics Subject Classification
+(2000)}\enspace}
+\def\subclass#1{\par\addvspace\medskipamount{\rightskip=0pt plus1cm
+\def\and{\ifhmode\unskip\nobreak\fi\ $\cdot$
+}\noindent\subclassname\ignorespaces#1\par}}
+%
+\def\PACSname{\textbf{PACS}\enspace}
+\def\PACS#1{\par\addvspace\medskipamount{\rightskip=0pt plus1cm
+\def\and{\ifhmode\unskip\nobreak\fi\ $\cdot$
+}\noindent\PACSname\ignorespaces#1\par}}
+%
+\def\CRclassname{{\bfseries CR Subject Classification}\enspace}
+\def\CRclass#1{\par\addvspace\medskipamount{\rightskip=0pt plus1cm
+\def\and{\ifhmode\unskip\nobreak\fi\ $\cdot$
+}\noindent\CRclassname\ignorespaces#1\par}}
+%
+\def\ESMname{\textbf{Electronic Supplementary Material}\enspace}
+\def\ESM#1{\par\addvspace\medskipamount
+\noindent\ESMname\ignorespaces#1\par}
+%
+\newcounter{inst}
+\newcounter{auth}
+\def\authdepth{2}
+\newdimen\instindent
+\newbox\authrun
+\newtoks\authorrunning
+\newbox\titrun
+\newtoks\titlerunning
+\def\authorfont{\bfseries}
+
+\def\combirunning#1{\gdef\@combi{#1}}
+\def\@combi{}
+\newbox\combirun
+%
+\def\ps@last{\def\@evenhead{\small\rlap{\thepage}\hfil
+\lastevenhead}}
+\newcounter{lastpage}
+\def\islastpageeven{\@ifundefined{lastpagenumber}
+{\setcounter{lastpage}{0}}{\setcounter{lastpage}{\lastpagenumber}}
+\ifnum\value{lastpage}>0
+   \ifodd\value{lastpage}%
+   \else
+      \if@smartrunh
+         \thispagestyle{last}%
+      \fi
+   \fi
+\fi}
+\def\getlastpagenumber{\clearpage
+\addtocounter{page}{-1}%
+   \immediate\write\@auxout{\string\gdef\string\lastpagenumber{\thepage}}%
+   \immediate\write\@auxout{\string\newlabel{LastPage}{{}{\thepage}}}%
+   \addtocounter{page}{1}}
+
+\def\journalname#1{\gdef\@journalname{#1}}
+
+\def\dedication#1{\gdef\@dedic{#1}}
+\def\@dedic{}
+
+\let\@date\undefined
+\def\notused{~}
+
+\def\institute#1{\gdef\@institute{#1}}
+
+\def\offprints#1{\begingroup
+\def\protect{\noexpand\protect\noexpand}\xdef\@thanks{\@thanks
+\protect\footnotetext[0]{\unskip\hskip-15pt{\itshape Send offprint requests
+to\/}: \ignorespaces#1}}\endgroup\ignorespaces}
+
+%\def\mail#1{\gdef\@mail{#1}}
+%\def\@mail{}
+
+\def\@thanks{}
+
+\def\@fnsymbol#1{\ifcase#1\or\star\or{\star\star}\or{\star\star\star}%
+   \or \dagger\or \ddagger\or
+   \mathchar "278\or \mathchar "27B\or \|\or **\or \dagger\dagger
+   \or \ddagger\ddagger \else\@ctrerr\fi\relax}
+%
+%\def\invthanks#1{\footnotetext[0]{\kern-\bibindent#1}}
+%
+\def\nothanksmarks{\def\thanks##1{\protected@xdef\@thanks{\@thanks
+        \protect\footnotetext[0]{\kern-\bibindent##1}}}}
+%
+\def\subtitle#1{\gdef\@subtitle{#1}}
+\def\@subtitle{}
+
+\def\headnote#1{\gdef\@headnote{#1}}
+\def\@headnote{}
+
+\def\papertype#1{\gdef\paper@type{\MakeUppercase{#1}}}
+\def\paper@type{}
+
+\def\ch@ckobl#1#2{\@ifundefined{@#1}
+ {\typeout{SVJour3 warning: Missing
+\expandafter\string\csname#1\endcsname}%
+  \csname #1\endcsname{#2}}
+ {}}
+%
+\def\ProcessRunnHead{%
+    \def\\{\unskip\ \ignorespaces}%
+    \def\thanks##1{\unskip{}}%
+    \instindent=\textwidth
+    \advance\instindent by-\headlineindent
+    \if!\the\titlerunning!\else
+      \edef\@title{\the\titlerunning}%
+    \fi
+    \global\setbox\titrun=\hbox{\small\rmfamily\unboldmath\ignorespaces\@title
+                                \unskip}%
+    \ifdim\wd\titrun>\instindent
+       \typeout{^^JSVJour3 Warning: Title too long for running head.}%
+       \typeout{Please supply a shorter form with \string\titlerunning
+                \space prior to \string\maketitle}%
+       \global\setbox\titrun=\hbox{\small\rmfamily
+       Title Suppressed Due to Excessive Length}%
+    \fi
+    \xdef\@title{\copy\titrun}%
+%
+    \if!\the\authorrunning!
+    \else
+      \setcounter{auth}{1}%
+      \edef\@author{\the\authorrunning}%
+    \fi
+    \ifnum\value{inst}>\authdepth
+       \def\stripauthor##1\and##2\endauthor{%
+       \protected@xdef\@author{##1\unskip\unskip\if!##2!\else\ et al.\fi}}%
+       \expandafter\stripauthor\@author\and\endauthor
+    \else
+       \gdef\and{\unskip, \ignorespaces}%
+       {\def\and{\noexpand\protect\noexpand\and}%
+       \protected@xdef\@author{\@author}}
+    \fi
+    \global\setbox\authrun=\hbox{\small\rmfamily\unboldmath\ignorespaces
+                                 \@author\unskip}%
+    \ifdim\wd\authrun>\instindent
+    \typeout{^^JSVJour3 Warning: Author name(s) too long for running head.
+             ^^JPlease supply a shorter form with \string\authorrunning
+             \space prior to \string\maketitle}%
+    \global\setbox\authrun=\hbox{\small\rmfamily Please give a shorter version
+          with: {\tt\string\authorrunning\space and
+             \string\titlerunning\space prior to \string\maketitle}}%
+    \fi
+    \xdef\@author{\copy\authrun}%
+    \markboth{\@author}{\@title}%
+}
+%
+\let\orithanks=\thanks
+\def\thanks#1{\ClassWarning{SVJour3}{\string\thanks\space may only be
+used inside of \string\title, \string\author,\MessageBreak
+and \string\date\space prior to \string\maketitle}}
+%
+\def\maketitle{\par\let\thanks=\orithanks
+\ch@ckobl{journalname}{Noname}
+\ch@ckobl{date}{the date of receipt and acceptance should be inserted
+later}
+\ch@ckobl{title}{A title should be given}
+\ch@ckobl{author}{Name(s) and initial(s) of author(s) should be given}
+\ch@ckobl{institute}{Address(es) of author(s) should be given}
+\begingroup
+%
+    \renewcommand\thefootnote{\@fnsymbol\c@footnote}%
+    \def\@makefnmark{$^{\@thefnmark}$}%
+    \renewcommand\@makefntext[1]{%
+    \noindent
+    \hb@xt@\bibindent{\hss\@makefnmark\enspace}##1\vrule height0pt
+    width0pt depth8pt}
+%
+ \def\lastand{\ifnum\value{inst}=2\relax
+                 \unskip{} \andname\
+              \else
+                 \unskip, \andname\
+              \fi}%
+ \def\and{\stepcounter{auth}\relax
+          \if@smartand
+             \ifnum\value{auth}=\value{inst}%
+                \lastand
+             \else
+                \unskip,
+             \fi
+          \else
+             \unskip,
+          \fi}%
+ \thispagestyle{empty}
+ \ifnum \col@number=\@ne
+   \@maketitle
+ \else
+   \twocolumn[\@maketitle]%
+ \fi
+%
+ \global\@topnum\z@
+ \if!\@thanks!\else
+    \@thanks
+\insert\footins{\vskip-3pt\hrule\@width\if@twocolumn\columnwidth
+\else 38mm\fi\vskip3pt}%
+ \fi
+ {\def\thanks##1{\unskip{}}%
+ \def\iand{\\[5pt]\let\and=\nand}%
+ \def\nand{\ifhmode\unskip\nobreak\fi\ $\cdot$ }%
+ \let\and=\nand
+ \def\at{\\\let\and=\iand}%
+ \footnotetext[0]{\kern-\bibindent
+ \ignorespaces\@institute}\vspace{5dd}}%
+%\if!\@mail!\else
+%   \footnotetext[0]{\kern-\bibindent\mailname\
+%   \ignorespaces\@mail}%
+%\fi
+%
+ \if@runhead
+    \ProcessRunnHead
+ \fi
+%
+ \endgroup
+ \setcounter{footnote}{0}
+ \global\let\thanks\relax
+ \global\let\maketitle\relax
+ \global\let\@maketitle\relax
+ \global\let\@thanks\@empty
+ \global\let\@author\@empty
+ \global\let\@date\@empty
+ \global\let\@title\@empty
+ \global\let\@subtitle\@empty
+ \global\let\title\relax
+ \global\let\author\relax
+ \global\let\date\relax
+ \global\let\and\relax}
+
+\def\makeheadbox{{%
+\hbox to0pt{\vbox{\baselineskip=10dd\hrule\hbox
+to\hsize{\vrule\kern3pt\vbox{\kern3pt
+\hbox{\bfseries\@journalname\ manuscript No.}
+\hbox{(will be inserted by the editor)}
+\kern3pt}\hfil\kern3pt\vrule}\hrule}%
+\hss}}}
+%
+\def\rubric{\setbox0=\hbox{\small\strut}\@tempdima=\ht0\advance
+\@tempdima\dp0\advance\@tempdima2\fboxsep\vrule\@height\@tempdima
+\@width\z@}
+\newdimen\rubricwidth
+%
+\def\@maketitle{\newpage
+\normalfont
+\vbox to0pt{\if@twocolumn\vskip-39pt\else\vskip-49pt\fi
+\nointerlineskip
+\makeheadbox\vss}\nointerlineskip
+\vbox to 0pt{\offinterlineskip\rubricwidth=\columnwidth
+%%%%\vskip-12.5pt          % -12.5pt
+\if@twocolumn\else % one column journal
+   \divide\rubricwidth by144\multiply\rubricwidth by89 % perform golden section
+   \vskip-\topskip
+\fi
+\hrule\@height0.35mm\noindent
+\advance\fboxsep by.25mm
+\global\advance\rubricwidth by0pt
+\rubric
+\vss}\vskip19.5pt    % war 9pt
+%
+\if@twocolumn\else
+ \gdef\footnoterule{%
+  \kern-3\p@
+  \hrule\@width38mm     % \columnwidth  \rubricwidth
+  \kern2.6\p@}
+\fi
+%
+ \setbox\authrun=\vbox\bgroup
+     \if@twocolumn
+        \hrule\@height10.5mm\@width0\p@
+     \else
+        \hrule\@height 2mm\@width0\p@
+     \fi
+     \pretolerance=10000
+     \rightskip=0pt plus 4cm
+    \nothanksmarks
+%   \if!\@headnote!\else
+%     \noindent
+%     {\LARGE\normalfont\itshape\ignorespaces\@headnote\par}\vskip 3.5mm
+%   \fi
+    {\LARGE\bfseries
+     \noindent\ignorespaces
+     \@title \par}\vskip 17pt\relax
+    \if!\@subtitle!\else
+      {\large\bfseries
+      \pretolerance=10000
+      \rightskip=0pt plus 3cm
+      \vskip-12pt
+%     \noindent\ignorespaces\@subtitle \par}\vskip 11.24pt\relax
+      \noindent\ignorespaces\@subtitle \par}\vskip 17pt\relax
+    \fi
+    {\authorfont
+    \setbox0=\vbox{\setcounter{auth}{1}\def\and{\stepcounter{auth} }%
+                   \hfuzz=2\textwidth\def\thanks##1{}\@author}%
+    \setcounter{footnote}{0}%
+    \global\value{inst}=\value{auth}%
+    \setcounter{auth}{1}%
+    \if@twocolumn
+       \rightskip43mm plus 4cm minus 3mm
+    \else % one column journal
+       \rightskip=\linewidth
+       \advance\rightskip by-\rubricwidth
+       \advance\rightskip by0pt plus 4cm minus 3mm
+    \fi
+%
+\def\and{\unskip\nobreak\enskip{\boldmath$\cdot$}\enskip\ignorespaces}%
+    \noindent\ignorespaces\@author\vskip7.23pt}
+%
+    \small
+    \if!\@dedic!\else
+       \par
+       \normalsize\it
+       \addvspace\baselineskip
+       \noindent\@dedic
+    \fi
+ \egroup % end of header box
+ \@tempdima=\headerboxheight
+ \advance\@tempdima by-\ht\authrun
+ \unvbox\authrun
+ \ifdim\@tempdima>0pt
+    \vrule width0pt height\@tempdima\par
+ \fi
+ \noindent{\small\@date\if@twocolumn\vskip 7.2mm\else\vskip 5.2mm\fi}
+ \global\@minipagetrue
+ \global\everypar{\global\@minipagefalse\global\everypar{}}%
+%\vskip22.47pt
+}
+%
+\if@mathematic
+   \def\vec#1{\ensuremath{\mathchoice
+                     {\mbox{\boldmath$\displaystyle\mathbf{#1}$}}
+                     {\mbox{\boldmath$\textstyle\mathbf{#1}$}}
+                     {\mbox{\boldmath$\scriptstyle\mathbf{#1}$}}
+                     {\mbox{\boldmath$\scriptscriptstyle\mathbf{#1}$}}}}
+\else
+   \def\vec#1{\ensuremath{\mathchoice
+                     {\mbox{\boldmath$\displaystyle#1$}}
+                     {\mbox{\boldmath$\textstyle#1$}}
+                     {\mbox{\boldmath$\scriptstyle#1$}}
+                     {\mbox{\boldmath$\scriptscriptstyle#1$}}}}
+\fi
+%
+\def\tens#1{\ensuremath{\mathsf{#1}}}
+%
+\setcounter{secnumdepth}{3}
+\newcounter {section}
+\newcounter {subsection}[section]
+\newcounter {subsubsection}[subsection]
+\newcounter {paragraph}[subsubsection]
+\newcounter {subparagraph}[paragraph]
+\renewcommand\thesection      {\@arabic\c@section}
+\renewcommand\thesubsection   {\thesection.\@arabic\c@subsection}
+\renewcommand\thesubsubsection{\thesubsection.\@arabic\c@subsubsection}
+\renewcommand\theparagraph    {\thesubsubsection.\@arabic\c@paragraph}
+\renewcommand\thesubparagraph {\theparagraph.\@arabic\c@subparagraph}
+%
+\def\@hangfrom#1{\setbox\@tempboxa\hbox{#1}%
+      \hangindent \z@\noindent\box\@tempboxa}
+%
+\def\@seccntformat#1{\csname the#1\endcsname\sectcounterend
+\hskip\betweenumberspace}
+%
+% \newif\if@sectrule
+% \if@twocolumn\else\let\@sectruletrue=\relax\fi
+% \if@avier\let\@sectruletrue=\relax\fi
+% \def\makesectrule{\if@sectrule\global\@sectrulefalse\null\vglue-\topskip
+% \hrule\nobreak\parskip=5pt\relax\fi}
+% %
+% \let\makesectruleori=\makesectrule
+% \def\restoresectrule{\global\let\makesectrule=\makesectruleori\global\@sectrulefalse}
+% \def\nosectrule{\let\makesectrule=\restoresectrule}
+%
+\def\@startsection#1#2#3#4#5#6{%
+  \if@noskipsec \leavevmode \fi
+  \par
+  \@tempskipa #4\relax
+  \@afterindenttrue
+  \ifdim \@tempskipa <\z@
+    \@tempskipa -\@tempskipa \@afterindentfalse
+  \fi
+  \if@nobreak
+    \everypar{}%
+  \else
+    \addpenalty\@secpenalty\addvspace\@tempskipa
+  \fi
+% \ifnum#2=1\relax\@sectruletrue\fi
+  \@ifstar
+    {\@ssect{#3}{#4}{#5}{#6}}%
+    {\@dblarg{\@sect{#1}{#2}{#3}{#4}{#5}{#6}}}}
+%
+\def\@sect#1#2#3#4#5#6[#7]#8{%
+  \ifnum #2>\c@secnumdepth
+    \let\@svsec\@empty
+  \else
+    \refstepcounter{#1}%
+    \protected@edef\@svsec{\@seccntformat{#1}\relax}%
+  \fi
+  \@tempskipa #5\relax
+  \ifdim \@tempskipa>\z@
+    \begingroup
+      #6{% \makesectrule
+        \@hangfrom{\hskip #3\relax\@svsec}%
+          \raggedright
+          \hyphenpenalty \@M%
+          \interlinepenalty \@M #8\@@par}%
+    \endgroup
+    \csname #1mark\endcsname{#7}%
+    \addcontentsline{toc}{#1}{%
+      \ifnum #2>\c@secnumdepth \else
+        \protect\numberline{\csname the#1\endcsname\sectcounterend}%
+      \fi
+      #7}%
+  \else
+    \def\@svsechd{%
+      #6{\hskip #3\relax
+      \@svsec #8\/\hskip\aftertext}%
+      \csname #1mark\endcsname{#7}%
+      \addcontentsline{toc}{#1}{%
+        \ifnum #2>\c@secnumdepth \else
+          \protect\numberline{\csname the#1\endcsname}%
+        \fi
+        #7}}%
+  \fi
+  \@xsect{#5}}
+%
+\def\@ssect#1#2#3#4#5{%
+  \@tempskipa #3\relax
+  \ifdim \@tempskipa>\z@
+    \begingroup
+      #4{% \makesectrule
+        \@hangfrom{\hskip #1}%
+          \interlinepenalty \@M #5\@@par}%
+    \endgroup
+  \else
+    \def\@svsechd{#4{\hskip #1\relax #5}}%
+  \fi
+  \@xsect{#3}}
+
+%
+% measures and setting of sections
+%
+\def\section{\@startsection{section}{1}{\z@}%
+    {-21dd plus-8pt minus-4pt}{10.5dd}
+     {\normalsize\bfseries\boldmath}}
+\def\subsection{\@startsection{subsection}{2}{\z@}%
+    {-21dd plus-8pt minus-4pt}{10.5dd}
+     {\normalsize\upshape}}
+\def\subsubsection{\@startsection{subsubsection}{3}{\z@}%
+    {-13dd plus-8pt minus-4pt}{10.5dd}
+     {\normalsize\itshape}}
+\def\paragraph{\@startsection{paragraph}{4}{\z@}%
+    {-13pt plus-8pt minus-4pt}{\z@}{\normalsize\itshape}}
+
+\setlength\leftmargini  {\parindent}
+\leftmargin  \leftmargini
+\setlength\leftmarginii {\parindent}
+\setlength\leftmarginiii {1.87em}
+\setlength\leftmarginiv  {1.7em}
+\setlength\leftmarginv  {.5em}
+\setlength\leftmarginvi {.5em}
+\setlength  \labelsep  {.5em}
+\setlength  \labelwidth{\leftmargini}
+\addtolength\labelwidth{-\labelsep}
+\@beginparpenalty -\@lowpenalty
+\@endparpenalty   -\@lowpenalty
+\@itempenalty     -\@lowpenalty
+\renewcommand\theenumi{\@arabic\c@enumi}
+\renewcommand\theenumii{\@alph\c@enumii}
+\renewcommand\theenumiii{\@roman\c@enumiii}
+\renewcommand\theenumiv{\@Alph\c@enumiv}
+\newcommand\labelenumi{\theenumi.}
+\newcommand\labelenumii{(\theenumii)}
+\newcommand\labelenumiii{\theenumiii.}
+\newcommand\labelenumiv{\theenumiv.}
+\renewcommand\p@enumii{\theenumi}
+\renewcommand\p@enumiii{\theenumi(\theenumii)}
+\renewcommand\p@enumiv{\p@enumiii\theenumiii}
+\newcommand\labelitemi{\normalfont\bfseries --}
+\newcommand\labelitemii{\normalfont\bfseries --}
+\newcommand\labelitemiii{$\m@th\bullet$}
+\newcommand\labelitemiv{$\m@th\cdot$}
+
+\if@spthms
+% definition of the "\spnewtheorem" command.
+%
+% Usage:
+%
+%     \spnewtheorem{env_nam}{caption}[within]{cap_font}{body_font}
+% or  \spnewtheorem{env_nam}[numbered_like]{caption}{cap_font}{body_font}
+% or  \spnewtheorem*{env_nam}{caption}{cap_font}{body_font}
+%
+% New is "cap_font" and "body_font". It stands for
+% fontdefinition of the caption and the text itself.
+%
+% "\spnewtheorem*" gives a theorem without number.
+%
+% A defined spnewthoerem environment is used as described
+% by Lamport.
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\def\@thmcountersep{}
+\def\@thmcounterend{}
+\newcommand\nocaption{\noexpand\@gobble}
+\newdimen\spthmsep \spthmsep=5pt
+
+\def\spnewtheorem{\@ifstar{\@sthm}{\@Sthm}}
+
+% definition of \spnewtheorem with number
+
+\def\@spnthm#1#2{%
+  \@ifnextchar[{\@spxnthm{#1}{#2}}{\@spynthm{#1}{#2}}}
+\def\@Sthm#1{\@ifnextchar[{\@spothm{#1}}{\@spnthm{#1}}}
+
+\def\@spxnthm#1#2[#3]#4#5{\expandafter\@ifdefinable\csname #1\endcsname
+   {\@definecounter{#1}\@addtoreset{#1}{#3}%
+   \expandafter\xdef\csname the#1\endcsname{\expandafter\noexpand
+     \csname the#3\endcsname \noexpand\@thmcountersep \@thmcounter{#1}}%
+   \expandafter\xdef\csname #1name\endcsname{#2}%
+   \global\@namedef{#1}{\@spthm{#1}{\csname #1name\endcsname}{#4}{#5}}%
+                              \global\@namedef{end#1}{\@endtheorem}}}
+
+\def\@spynthm#1#2#3#4{\expandafter\@ifdefinable\csname #1\endcsname
+   {\@definecounter{#1}%
+   \expandafter\xdef\csname the#1\endcsname{\@thmcounter{#1}}%
+   \expandafter\xdef\csname #1name\endcsname{#2}%
+   \global\@namedef{#1}{\@spthm{#1}{\csname #1name\endcsname}{#3}{#4}}%
+                               \global\@namedef{end#1}{\@endtheorem}}}
+
+\def\@spothm#1[#2]#3#4#5{%
+  \@ifundefined{c@#2}{\@latexerr{No theorem environment `#2' defined}\@eha}%
+  {\expandafter\@ifdefinable\csname #1\endcsname
+  {\global\@namedef{the#1}{\@nameuse{the#2}}%
+  \expandafter\xdef\csname #1name\endcsname{#3}%
+  \global\@namedef{#1}{\@spthm{#2}{\csname #1name\endcsname}{#4}{#5}}%
+  \global\@namedef{end#1}{\@endtheorem}}}}
+
+\def\@spthm#1#2#3#4{\topsep 7\p@ \@plus2\p@ \@minus4\p@
+\labelsep=\spthmsep\refstepcounter{#1}%
+\@ifnextchar[{\@spythm{#1}{#2}{#3}{#4}}{\@spxthm{#1}{#2}{#3}{#4}}}
+
+\def\@spxthm#1#2#3#4{\@spbegintheorem{#2}{\csname the#1\endcsname}{#3}{#4}%
+                    \ignorespaces}
+
+\def\@spythm#1#2#3#4[#5]{\@spopargbegintheorem{#2}{\csname
+       the#1\endcsname}{#5}{#3}{#4}\ignorespaces}
+
+\def\normalthmheadings{\def\@spbegintheorem##1##2##3##4{\trivlist\normalfont
+                 \item[\hskip\labelsep{##3##1\ ##2\@thmcounterend}]##4}
+\def\@spopargbegintheorem##1##2##3##4##5{\trivlist
+      \item[\hskip\labelsep{##4##1\ ##2}]{##4(##3)\@thmcounterend\ }##5}}
+\normalthmheadings
+
+\def\reversethmheadings{\def\@spbegintheorem##1##2##3##4{\trivlist\normalfont
+                 \item[\hskip\labelsep{##3##2\ ##1\@thmcounterend}]##4}
+\def\@spopargbegintheorem##1##2##3##4##5{\trivlist
+      \item[\hskip\labelsep{##4##2\ ##1}]{##4(##3)\@thmcounterend\ }##5}}
+
+% definition of \spnewtheorem* without number
+
+\def\@sthm#1#2{\@Ynthm{#1}{#2}}
+
+\def\@Ynthm#1#2#3#4{\expandafter\@ifdefinable\csname #1\endcsname
+   {\global\@namedef{#1}{\@Thm{\csname #1name\endcsname}{#3}{#4}}%
+    \expandafter\xdef\csname #1name\endcsname{#2}%
+    \global\@namedef{end#1}{\@endtheorem}}}
+
+\def\@Thm#1#2#3{\topsep 7\p@ \@plus2\p@ \@minus4\p@
+\@ifnextchar[{\@Ythm{#1}{#2}{#3}}{\@Xthm{#1}{#2}{#3}}}
+
+\def\@Xthm#1#2#3{\@Begintheorem{#1}{#2}{#3}\ignorespaces}
+
+\def\@Ythm#1#2#3[#4]{\@Opargbegintheorem{#1}
+       {#4}{#2}{#3}\ignorespaces}
+
+\def\@Begintheorem#1#2#3{#3\trivlist
+                           \item[\hskip\labelsep{#2#1\@thmcounterend}]}
+
+\def\@Opargbegintheorem#1#2#3#4{#4\trivlist
+      \item[\hskip\labelsep{#3#1}]{#3(#2)\@thmcounterend\ }}
+
+% initialize theorem environment
+
+\if@envcntsect
+   \def\@thmcountersep{.}
+   \spnewtheorem{theorem}{Theorem}[section]{\bfseries}{\itshape}
+\else
+   \spnewtheorem{theorem}{Theorem}{\bfseries}{\itshape}
+   \if@envcntreset
+      \@addtoreset{theorem}{section}
+   \else
+      \@addtoreset{theorem}{chapter}
+   \fi
+\fi
+
+%definition of divers theorem environments
+\spnewtheorem*{claim}{Claim}{\itshape}{\rmfamily}
+\spnewtheorem*{proof}{Proof}{\itshape}{\rmfamily}
+\if@envcntsame % all environments like "Theorem" - using its counter
+   \def\spn@wtheorem#1#2#3#4{\@spothm{#1}[theorem]{#2}{#3}{#4}}
+\else % all environments with their own counter
+   \if@envcntsect % show section counter
+      \def\spn@wtheorem#1#2#3#4{\@spxnthm{#1}{#2}[section]{#3}{#4}}
+   \else % not numbered with section
+      \if@envcntreset
+         \def\spn@wtheorem#1#2#3#4{\@spynthm{#1}{#2}{#3}{#4}
+                                   \@addtoreset{#1}{section}}
+      \else
+         \let\spn@wtheorem=\@spynthm
+      \fi
+   \fi
+\fi
+%
+\let\spdefaulttheorem=\spn@wtheorem
+%
+\spn@wtheorem{case}{Case}{\itshape}{\rmfamily}
+\spn@wtheorem{conjecture}{Conjecture}{\itshape}{\rmfamily}
+\spn@wtheorem{corollary}{Corollary}{\bfseries}{\itshape}
+\spn@wtheorem{definition}{Definition}{\bfseries}{\rmfamily}
+\spn@wtheorem{example}{Example}{\itshape}{\rmfamily}
+\spn@wtheorem{exercise}{Exercise}{\bfseries}{\rmfamily}
+\spn@wtheorem{lemma}{Lemma}{\bfseries}{\itshape}
+\spn@wtheorem{note}{Note}{\itshape}{\rmfamily}
+\spn@wtheorem{problem}{Problem}{\bfseries}{\rmfamily}
+\spn@wtheorem{property}{Property}{\itshape}{\rmfamily}
+\spn@wtheorem{proposition}{Proposition}{\bfseries}{\itshape}
+\spn@wtheorem{question}{Question}{\itshape}{\rmfamily}
+\spn@wtheorem{solution}{Solution}{\bfseries}{\rmfamily}
+\spn@wtheorem{remark}{Remark}{\itshape}{\rmfamily}
+%
+\newenvironment{theopargself}
+    {\def\@spopargbegintheorem##1##2##3##4##5{\trivlist
+         \item[\hskip\labelsep{##4##1\ ##2}]{##4##3\@thmcounterend\ }##5}
+     \def\@Opargbegintheorem##1##2##3##4{##4\trivlist
+         \item[\hskip\labelsep{##3##1}]{##3##2\@thmcounterend\ }}}{}
+\newenvironment{theopargself*}
+    {\def\@spopargbegintheorem##1##2##3##4##5{\trivlist
+         \item[\hskip\labelsep{##4##1\ ##2}]{\hspace*{-\labelsep}##4##3\@thmcounterend}##5}
+     \def\@Opargbegintheorem##1##2##3##4{##4\trivlist
+         \item[\hskip\labelsep{##3##1}]{\hspace*{-\labelsep}##3##2\@thmcounterend}}}{}
+%
+\fi
+
+\def\@takefromreset#1#2{%
+    \def\@tempa{#1}%
+    \let\@tempd\@elt
+    \def\@elt##1{%
+        \def\@tempb{##1}%
+        \ifx\@tempa\@tempb\else
+            \@addtoreset{##1}{#2}%
+        \fi}%
+    \expandafter\expandafter\let\expandafter\@tempc\csname cl@#2\endcsname
+    \expandafter\def\csname cl@#2\endcsname{}%
+    \@tempc
+    \let\@elt\@tempd}
+
+\def\squareforqed{\hbox{\rlap{$\sqcap$}$\sqcup$}}
+\def\qed{\ifmmode\else\unskip\quad\fi\squareforqed}
+\def\smartqed{\def\qed{\ifmmode\squareforqed\else{\unskip\nobreak\hfil
+\penalty50\hskip1em\null\nobreak\hfil\squareforqed
+\parfillskip=0pt\finalhyphendemerits=0\endgraf}\fi}}
+
+% Define `abstract' environment
+\def\abstract{\topsep=0pt\partopsep=0pt\parsep=0pt\itemsep=0pt\relax
+\trivlist\item[\hskip\labelsep
+{\bfseries\abstractname}]\if!\abstractname!\hskip-\labelsep\fi}
+\if@twocolumn
+% \if@avier
+%   \def\endabstract{\endtrivlist\addvspace{5mm}\strich}
+%   \def\strich{\hrule\vskip1ptplus12pt}
+% \else
+    \def\endabstract{\endtrivlist\addvspace{3mm}}
+% \fi
+\else
+\fi
+%
+\newenvironment{verse}
+               {\let\\\@centercr
+                \list{}{\itemsep      \z@
+                        \itemindent   -1.5em%
+                        \listparindent\itemindent
+                        \rightmargin  \leftmargin
+                        \advance\leftmargin 1.5em}%
+                \item\relax}
+               {\endlist}
+\newenvironment{quotation}
+               {\list{}{\listparindent 1.5em%
+                        \itemindent    \listparindent
+                        \rightmargin   \leftmargin
+                        \parsep        \z@ \@plus\p@}%
+                \item\relax}
+               {\endlist}
+\newenvironment{quote}
+               {\list{}{\rightmargin\leftmargin}%
+                \item\relax}
+               {\endlist}
+\newcommand\appendix{\par\small
+  \setcounter{section}{0}%
+  \setcounter{subsection}{0}%
+  \renewcommand\thesection{\@Alph\c@section}}
+\setlength\arraycolsep{1.5\p@}
+\setlength\tabcolsep{6\p@}
+\setlength\arrayrulewidth{.4\p@}
+\setlength\doublerulesep{2\p@}
+\setlength\tabbingsep{\labelsep}
+\skip\@mpfootins = \skip\footins
+\setlength\fboxsep{3\p@}
+\setlength\fboxrule{.4\p@}
+\renewcommand\theequation{\@arabic\c@equation}
+\newcounter{figure}
+\renewcommand\thefigure{\@arabic\c@figure}
+\def\fps@figure{tbp}
+\def\ftype@figure{1}
+\def\ext@figure{lof}
+\def\fnum@figure{\figurename~\thefigure}
+\newenvironment{figure}
+               {\@float{figure}}
+               {\end@float}
+\newenvironment{figure*}
+               {\@dblfloat{figure}}
+               {\end@dblfloat}
+\newcounter{table}
+\renewcommand\thetable{\@arabic\c@table}
+\def\fps@table{tbp}
+\def\ftype@table{2}
+\def\ext@table{lot}
+\def\fnum@table{\tablename~\thetable}
+\newenvironment{table}
+               {\@float{table}}
+               {\end@float}
+\newenvironment{table*}
+               {\@dblfloat{table}}
+               {\end@dblfloat}
+%
+\def \@floatboxreset {%
+        \reset@font
+        \small
+        \@setnobreak
+        \@setminipage
+}
+%
+\newcommand{\tableheadseprule}{\noalign{\hrule height.375mm}}
+%
+\newlength\abovecaptionskip
+\newlength\belowcaptionskip
+\setlength\abovecaptionskip{10\p@}
+\setlength\belowcaptionskip{0\p@}
+\newcommand\leftlegendglue{}
+
+\def\fig@type{figure}
+
+\newdimen\figcapgap\figcapgap=3pt
+\newdimen\tabcapgap\tabcapgap=5.5pt
+
+\@ifundefined{floatlegendstyle}{\def\floatlegendstyle{\bfseries}}{}
+
+\long\def\@caption#1[#2]#3{\par\addcontentsline{\csname
+  ext@#1\endcsname}{#1}{\protect\numberline{\csname
+  the#1\endcsname}{\ignorespaces #2}}\begingroup
+    \@parboxrestore
+    \@makecaption{\csname fnum@#1\endcsname}{\ignorespaces #3}\par
+  \endgroup}
+
+\def\capstrut{\vrule\@width\z@\@height\topskip}
+
+\@ifundefined{captionstyle}{\def\captionstyle{\normalfont\small}}{}
+
+\long\def\@makecaption#1#2{%
+ \captionstyle
+ \ifx\@captype\fig@type
+   \vskip\figcapgap
+ \fi
+ \setbox\@tempboxa\hbox{{\floatlegendstyle #1\floatcounterend}%
+ \capstrut #2}%
+ \ifdim \wd\@tempboxa >\hsize
+   {\floatlegendstyle #1\floatcounterend}\capstrut #2\par
+ \else
+   \hbox to\hsize{\leftlegendglue\unhbox\@tempboxa\hfil}%
+ \fi
+ \ifx\@captype\fig@type\else
+   \vskip\tabcapgap
+ \fi}
+
+\newdimen\figgap\figgap=1cc
+\long\def\@makesidecaption#1#2{%
+   \parbox[b]{\@tempdimb}{\captionstyle{\floatlegendstyle
+                                         #1\floatcounterend}#2}}
+\def\sidecaption#1\caption{%
+\setbox\@tempboxa=\hbox{#1\unskip}%
+\if@twocolumn
+ \ifdim\hsize<\textwidth\else
+   \ifdim\wd\@tempboxa<\columnwidth
+      \typeout{Double column float fits into single column -
+            ^^Jyou'd better switch the environment. }%
+   \fi
+ \fi
+\fi
+\@tempdimb=\hsize
+\advance\@tempdimb by-\figgap
+\advance\@tempdimb by-\wd\@tempboxa
+\ifdim\@tempdimb<3cm
+    \typeout{\string\sidecaption: No sufficient room for the legend;
+             using normal \string\caption. }%
+   \unhbox\@tempboxa
+   \let\@capcommand=\@caption
+\else
+   \let\@capcommand=\@sidecaption
+   \leavevmode
+   \unhbox\@tempboxa
+   \hfill
+\fi
+\refstepcounter\@captype
+\@dblarg{\@capcommand\@captype}}
+
+\long\def\@sidecaption#1[#2]#3{\addcontentsline{\csname
+  ext@#1\endcsname}{#1}{\protect\numberline{\csname
+  the#1\endcsname}{\ignorespaces #2}}\begingroup
+    \@parboxrestore
+    \@makesidecaption{\csname fnum@#1\endcsname}{\ignorespaces #3}\par
+  \endgroup}
+
+% Define `acknowledgement' environment
+\def\acknowledgement{\par\addvspace{17pt}\small\rmfamily
+\trivlist\if!\ackname!\item[]\else
+\item[\hskip\labelsep
+{\bfseries\ackname}]\fi}
+\def\endacknowledgement{\endtrivlist\addvspace{6pt}}
+\newenvironment{acknowledgements}{\begin{acknowledgement}}
+{\end{acknowledgement}}
+% Define `noteadd' environment
+\def\noteadd{\par\addvspace{17pt}\small\rmfamily
+\trivlist\item[\hskip\labelsep
+{\itshape\noteaddname}]}
+\def\endnoteadd{\endtrivlist\addvspace{6pt}}
+
+\DeclareOldFontCommand{\rm}{\normalfont\rmfamily}{\mathrm}
+\DeclareOldFontCommand{\sf}{\normalfont\sffamily}{\mathsf}
+\DeclareOldFontCommand{\tt}{\normalfont\ttfamily}{\mathtt}
+\DeclareOldFontCommand{\bf}{\normalfont\bfseries}{\mathbf}
+\DeclareOldFontCommand{\it}{\normalfont\itshape}{\mathit}
+\DeclareOldFontCommand{\sl}{\normalfont\slshape}{\@nomath\sl}
+\DeclareOldFontCommand{\sc}{\normalfont\scshape}{\@nomath\sc}
+\DeclareRobustCommand*\cal{\@fontswitch\relax\mathcal}
+\DeclareRobustCommand*\mit{\@fontswitch\relax\mathnormal}
+\newcommand\@pnumwidth{1.55em}
+\newcommand\@tocrmarg{2.55em}
+\newcommand\@dotsep{4.5}
+\setcounter{tocdepth}{1}
+\newcommand\tableofcontents{%
+    \section*{\contentsname}%
+    \@starttoc{toc}%
+    \addtocontents{toc}{\begingroup\protect\small}%
+    \AtEndDocument{\addtocontents{toc}{\endgroup}}%
+    }
+\newcommand*\l@part[2]{%
+  \ifnum \c@tocdepth >-2\relax
+    \addpenalty\@secpenalty
+    \addvspace{2.25em \@plus\p@}%
+    \begingroup
+      \setlength\@tempdima{3em}%
+      \parindent \z@ \rightskip \@pnumwidth
+      \parfillskip -\@pnumwidth
+      {\leavevmode
+       \large \bfseries #1\hfil \hb@xt@\@pnumwidth{\hss #2}}\par
+       \nobreak
+       \if@compatibility
+         \global\@nobreaktrue
+         \everypar{\global\@nobreakfalse\everypar{}}%
+      \fi
+    \endgroup
+  \fi}
+\newcommand*\l@section{\@dottedtocline{1}{0pt}{1.5em}}
+\newcommand*\l@subsection{\@dottedtocline{2}{1.5em}{2.3em}}
+\newcommand*\l@subsubsection{\@dottedtocline{3}{3.8em}{3.2em}}
+\newcommand*\l@paragraph{\@dottedtocline{4}{7.0em}{4.1em}}
+\newcommand*\l@subparagraph{\@dottedtocline{5}{10em}{5em}}
+\newcommand\listoffigures{%
+    \section*{\listfigurename
+      \@mkboth{\listfigurename}%
+              {\listfigurename}}%
+    \@starttoc{lof}%
+    }
+\newcommand*\l@figure{\@dottedtocline{1}{1.5em}{2.3em}}
+\newcommand\listoftables{%
+    \section*{\listtablename
+      \@mkboth{\listtablename}{\listtablename}}%
+    \@starttoc{lot}%
+    }
+\let\l@table\l@figure
+\newdimen\bibindent
+\setlength\bibindent{\parindent}
+\def\@biblabel#1{#1.}
+\def\@lbibitem[#1]#2{\item[{[#1]}\hfill]\if@filesw
+      {\let\protect\noexpand
+       \immediate
+       \write\@auxout{\string\bibcite{#2}{#1}}}\fi\ignorespaces}
+\newenvironment{thebibliography}[1]
+     {\section*{\refname
+        \@mkboth{\refname}{\refname}}\small
+      \list{\@biblabel{\@arabic\c@enumiv}}%
+           {\settowidth\labelwidth{\@biblabel{#1}}%
+            \leftmargin\labelwidth
+            \advance\leftmargin\labelsep
+            \@openbib@code
+            \usecounter{enumiv}%
+            \let\p@enumiv\@empty
+            \renewcommand\theenumiv{\@arabic\c@enumiv}}%
+      \sloppy\clubpenalty4000\widowpenalty4000%
+      \sfcode`\.\@m}
+     {\def\@noitemerr
+       {\@latex@warning{Empty `thebibliography' environment}}%
+      \endlist}
+%
+\newcount\@tempcntc
+\def\@citex[#1]#2{\if@filesw\immediate\write\@auxout{\string\citation{#2}}\fi
+  \@tempcnta\z@\@tempcntb\m@ne\def\@citea{}\@cite{\@for\@citeb:=#2\do
+    {\@ifundefined
+       {b@\@citeb}{\@citeo\@tempcntb\m@ne\@citea\def\@citea{,}{\bfseries
+        ?}\@warning
+       {Citation `\@citeb' on page \thepage \space undefined}}%
+    {\setbox\z@\hbox{\global\@tempcntc0\csname b@\@citeb\endcsname\relax}%
+     \ifnum\@tempcntc=\z@ \@citeo\@tempcntb\m@ne
+       \@citea\def\@citea{,\hskip0.1em\ignorespaces}\hbox{\csname b@\@citeb\endcsname}%
+     \else
+      \advance\@tempcntb\@ne
+      \ifnum\@tempcntb=\@tempcntc
+      \else\advance\@tempcntb\m@ne\@citeo
+      \@tempcnta\@tempcntc\@tempcntb\@tempcntc\fi\fi}}\@citeo}{#1}}
+\def\@citeo{\ifnum\@tempcnta>\@tempcntb\else
+            \@citea\def\@citea{,\hskip0.1em\ignorespaces}%
+  \ifnum\@tempcnta=\@tempcntb\the\@tempcnta\else
+   {\advance\@tempcnta\@ne\ifnum\@tempcnta=\@tempcntb \else \def\@citea{--}\fi
+    \advance\@tempcnta\m@ne\the\@tempcnta\@citea\the\@tempcntb}\fi\fi}
+%
+\newcommand\newblock{\hskip .11em\@plus.33em\@minus.07em}
+\let\@openbib@code\@empty
+\newenvironment{theindex}
+               {\if@twocolumn
+                  \@restonecolfalse
+                \else
+                  \@restonecoltrue
+                \fi
+                \columnseprule \z@
+                \columnsep 35\p@
+                \twocolumn[\section*{\indexname}]%
+                \@mkboth{\indexname}{\indexname}%
+                \thispagestyle{plain}\parindent\z@
+                \parskip\z@ \@plus .3\p@\relax
+                \let\item\@idxitem}
+               {\if@restonecol\onecolumn\else\clearpage\fi}
+\newcommand\@idxitem{\par\hangindent 40\p@}
+\newcommand\subitem{\@idxitem \hspace*{20\p@}}
+\newcommand\subsubitem{\@idxitem \hspace*{30\p@}}
+\newcommand\indexspace{\par \vskip 10\p@ \@plus5\p@ \@minus3\p@\relax}
+
+\if@twocolumn
+ \renewcommand\footnoterule{%
+  \kern-3\p@
+  \hrule\@width\columnwidth
+  \kern2.6\p@}
+\else
+ \renewcommand\footnoterule{%
+  \kern-3\p@
+  \hrule\@width.382\columnwidth
+  \kern2.6\p@}
+\fi
+\newcommand\@makefntext[1]{%
+    \noindent
+    \hb@xt@\bibindent{\hss\@makefnmark\enspace}#1}
+%
+\def\trans@english{\switcht@albion}
+\def\trans@french{\switcht@francais}
+\def\trans@german{\switcht@deutsch}
+\newenvironment{translation}[1]{\if!#1!\else
+\@ifundefined{selectlanguage}{\csname trans@#1\endcsname}{\selectlanguage{#1}}%
+\fi}{}
+% languages
+% English section
+\def\switcht@albion{%\typeout{English spoken.}%
+ \def\abstractname{Abstract}%
+ \def\ackname{Acknowledgements}%
+ \def\andname{and}%
+ \def\lastandname{, and}%
+ \def\appendixname{Appendix}%
+ \def\chaptername{Chapter}%
+ \def\claimname{Claim}%
+ \def\conjecturename{Conjecture}%
+ \def\contentsname{Contents}%
+ \def\corollaryname{Corollary}%
+ \def\definitionname{Definition}%
+ \def\emailname{E-mail}%
+ \def\examplename{Example}%
+ \def\exercisename{Exercise}%
+ \def\figurename{Fig.}%
+ \def\keywordname{{\bfseries Keywords}}%
+ \def\indexname{Index}%
+ \def\lemmaname{Lemma}%
+ \def\contriblistname{List of Contributors}%
+ \def\listfigurename{List of Figures}%
+ \def\listtablename{List of Tables}%
+ \def\mailname{{\itshape Correspondence to\/}:}%
+ \def\noteaddname{Note added in proof}%
+ \def\notename{Note}%
+ \def\partname{Part}%
+ \def\problemname{Problem}%
+ \def\proofname{Proof}%
+ \def\propertyname{Property}%
+ \def\questionname{Question}%
+ \def\refname{References}%
+ \def\remarkname{Remark}%
+ \def\seename{see}%
+ \def\solutionname{Solution}%
+ \def\tablename{Table}%
+ \def\theoremname{Theorem}%
+}\switcht@albion % make English default
+%
+% French section
+\def\switcht@francais{\svlanginfo
+%\typeout{On parle francais.}%
+ \def\abstractname{R\'esum\'e\runinend}%
+ \def\ackname{Remerciements\runinend}%
+ \def\andname{et}%
+ \def\lastandname{ et}%
+ \def\appendixname{Appendice}%
+ \def\chaptername{Chapitre}%
+ \def\claimname{Pr\'etention}%
+ \def\conjecturename{Hypoth\`ese}%
+ \def\contentsname{Table des mati\`eres}%
+ \def\corollaryname{Corollaire}%
+ \def\definitionname{D\'efinition}%
+ \def\emailname{E-mail}%
+ \def\examplename{Exemple}%
+ \def\exercisename{Exercice}%
+ \def\figurename{Fig.}%
+ \def\keywordname{{\bfseries Mots-cl\'e\runinend}}%
+ \def\indexname{Index}%
+ \def\lemmaname{Lemme}%
+ \def\contriblistname{Liste des contributeurs}%
+ \def\listfigurename{Liste des figures}%
+ \def\listtablename{Liste des tables}%
+ \def\mailname{{\itshape Correspondence to\/}:}%
+ \def\noteaddname{Note ajout\'ee \`a l'\'epreuve}%
+ \def\notename{Remarque}%
+ \def\partname{Partie}%
+ \def\problemname{Probl\`eme}%
+ \def\proofname{Preuve}%
+ \def\propertyname{Caract\'eristique}%
+%\def\propositionname{Proposition}%
+ \def\questionname{Question}%
+ \def\refname{Bibliographie}%
+ \def\remarkname{Remarque}%
+ \def\seename{voyez}%
+ \def\solutionname{Solution}%
+%\def\subclassname{{\it Subject Classifications\/}:}%
+ \def\tablename{Tableau}%
+ \def\theoremname{Th\'eor\`eme}%
+}
+%
+% German section
+\def\switcht@deutsch{\svlanginfo
+%\typeout{Man spricht deutsch.}%
+ \def\abstractname{Zusammenfassung\runinend}%
+ \def\ackname{Danksagung\runinend}%
+ \def\andname{und}%
+ \def\lastandname{ und}%
+ \def\appendixname{Anhang}%
+ \def\chaptername{Kapitel}%
+ \def\claimname{Behauptung}%
+ \def\conjecturename{Hypothese}%
+ \def\contentsname{Inhaltsverzeichnis}%
+ \def\corollaryname{Korollar}%
+%\def\definitionname{Definition}%
+ \def\emailname{E-Mail}%
+ \def\examplename{Beispiel}%
+ \def\exercisename{\"Ubung}%
+ \def\figurename{Abb.}%
+ \def\keywordname{{\bfseries Schl\"usselw\"orter\runinend}}%
+ \def\indexname{Index}%
+%\def\lemmaname{Lemma}%
+ \def\contriblistname{Mitarbeiter}%
+ \def\listfigurename{Abbildungsverzeichnis}%
+ \def\listtablename{Tabellenverzeichnis}%
+ \def\mailname{{\itshape Correspondence to\/}:}%
+ \def\noteaddname{Nachtrag}%
+ \def\notename{Anmerkung}%
+ \def\partname{Teil}%
+%\def\problemname{Problem}%
+ \def\proofname{Beweis}%
+ \def\propertyname{Eigenschaft}%
+%\def\propositionname{Proposition}%
+ \def\questionname{Frage}%
+ \def\refname{Literatur}%
+ \def\remarkname{Anmerkung}%
+ \def\seename{siehe}%
+ \def\solutionname{L\"osung}%
+%\def\subclassname{{\it Subject Classifications\/}:}%
+ \def\tablename{Tabelle}%
+%\def\theoremname{Theorem}%
+}
+\newcommand\today{}
+\edef\today{\ifcase\month\or
+  January\or February\or March\or April\or May\or June\or
+  July\or August\or September\or October\or November\or December\fi
+  \space\number\day, \number\year}
+\setlength\columnsep{1.5cc}
+\setlength\columnseprule{0\p@}
+%
+\frenchspacing
+\clubpenalty=10000
+\widowpenalty=10000
+\def\thisbottomragged{\def\@textbottom{\vskip\z@ plus.0001fil
+\global\let\@textbottom\relax}}
+\pagestyle{headings}
+\pagenumbering{arabic}
+\if@twocolumn
+   \twocolumn
+\fi
+%\if@avier
+%   \onecolumn
+%   \setlength{\textwidth}{156mm}
+%   \setlength{\textheight}{226mm}
+%\fi
+\if@referee
+   \makereferee
+\fi
+\flushbottom
+\endinput
+%%
+%% End of file `svjour3.cls'.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/.checkstyle	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<fileset-config file-format-version="1.2.0" simple-config="true" sync-formatter="false">
+  <local-check-config name="C1X Checkstyle checks" location=".checkstyle_checks.xml" type="project" description="">
+    <additional-data name="protect-config-file" value="false"/>
+  </local-check-config>
+  <fileset name="all" enabled="true" check-config-name="C1X Checkstyle checks" local="true">
+    <file-match-pattern match-pattern="." include-pattern="true"/>
+  </fileset>
+</fileset-config>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/.checkstyle_checks.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,191 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN" "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
+
+<!--
+    This configuration file was written by the eclipse-cs plugin configuration editor
+-->
+<!--
+    Checkstyle-Configuration: C1X Checkstyle checks
+    Description: none
+-->
+<module name="Checker">
+  <property name="severity" value="warning"/>
+  <module name="TreeWalker">
+    <property name="tabWidth" value="4"/>
+    <module name="FileContentsHolder"/>
+    <module name="JavadocStyle">
+      <property name="checkHtml" value="false"/>
+    </module>
+    <module name="LocalFinalVariableName"/>
+    <module name="LocalVariableName"/>
+    <module name="MemberName">
+      <property name="format" value="^(([a-z][a-zA-Z0-9]*$)|(_[A-Z][a-zA-Z0-9]*_[a-z][a-zA-Z0-9]*$))"/>
+    </module>
+    <module name="MethodName">
+      <property name="format" value="^[a-z][a-z_A-Z0-9]*$"/>
+    </module>
+    <module name="PackageName"/>
+    <module name="ParameterName"/>
+    <module name="TypeName">
+      <property name="format" value="^[A-Z][_a-zA-Z0-9]*$"/>
+    </module>
+    <module name="RedundantImport"/>
+    <module name="LineLength">
+      <property name="max" value="250"/>
+    </module>
+    <module name="MethodParamPad"/>
+    <module name="NoWhitespaceAfter">
+      <property name="tokens" value="ARRAY_INIT,BNOT,DEC,DOT,INC,LNOT,UNARY_MINUS,UNARY_PLUS"/>
+    </module>
+    <module name="NoWhitespaceBefore">
+      <property name="tokens" value="SEMI,DOT,POST_DEC,POST_INC"/>
+    </module>
+    <module name="ParenPad"/>
+    <module name="TypecastParenPad">
+      <property name="tokens" value="RPAREN,TYPECAST"/>
+    </module>
+    <module name="WhitespaceAfter"/>
+    <module name="WhitespaceAround">
+      <property name="tokens" value="ASSIGN,BAND,BAND_ASSIGN,BOR,BOR_ASSIGN,BSR,BSR_ASSIGN,BXOR,BXOR_ASSIGN,COLON,DIV,DIV_ASSIGN,EQUAL,GE,GT,LAND,LE,LITERAL_ASSERT,LITERAL_CATCH,LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_FOR,LITERAL_IF,LITERAL_RETURN,LITERAL_SYNCHRONIZED,LITERAL_TRY,LITERAL_WHILE,LOR,LT,MINUS,MINUS_ASSIGN,MOD,MOD_ASSIGN,NOT_EQUAL,PLUS,PLUS_ASSIGN,QUESTION,SL,SLIST,SL_ASSIGN,SR,SR_ASSIGN,STAR,STAR_ASSIGN,LITERAL_ASSERT,TYPE_EXTENSION_AND"/>
+    </module>
+    <module name="RedundantModifier"/>
+    <module name="AvoidNestedBlocks">
+      <property name="allowInSwitchCase" value="true"/>
+    </module>
+    <module name="EmptyBlock">
+      <property name="option" value="text"/>
+      <property name="tokens" value="LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_IF,LITERAL_TRY,LITERAL_WHILE,STATIC_INIT"/>
+    </module>
+    <module name="LeftCurly"/>
+    <module name="NeedBraces"/>
+    <module name="RightCurly"/>
+    <module name="DoubleCheckedLocking">
+      <property name="severity" value="error"/>
+    </module>
+    <module name="EmptyStatement"/>
+    <module name="HiddenField">
+      <property name="severity" value="ignore"/>
+      <property name="ignoreConstructorParameter" value="true"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="FinalClass"/>
+    <module name="HideUtilityClassConstructor">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="ArrayTypeStyle"/>
+    <module name="UpperEll"/>
+    <module name="FallThrough"/>
+    <module name="FinalLocalVariable">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="MultipleVariableDeclarations"/>
+    <module name="StringLiteralEquality">
+      <property name="severity" value="error"/>
+    </module>
+    <module name="SuperFinalize"/>
+    <module name="UnnecessaryParentheses">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="Indentation">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="StaticVariableName">
+      <property name="format" value="^[A-Za-z][a-zA-Z0-9]*$"/>
+    </module>
+    <module name="EmptyForInitializerPad"/>
+    <module name="EmptyForIteratorPad"/>
+    <module name="ModifierOrder"/>
+    <module name="DefaultComesLast"/>
+    <module name="InnerAssignment">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="JUnitTestCase"/>
+    <module name="ModifiedControlVariable"/>
+    <module name="MutableException"/>
+    <module name="ParameterAssignment">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="RegexpSinglelineJava">
+      <property name="format" value="\s$"/>
+      <property name="message" value="Illegal trailing whitespace(s) at the end of the line."/>
+      <property name="ignoreComments" value="true"/>
+      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Checks for trailing spaces at the end of a line"/>
+    </module>
+    <module name="RegexpSinglelineJava">
+      <property name="format" value=" ,"/>
+      <property name="ignoreComments" value="true"/>
+      <metadata name="com.atlassw.tools.eclipse.checkstyle.customMessage" value="Illegal whitespace before a comma."/>
+      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Checks for whitespace before a comma."/>
+    </module>
+  </module>
+  <module name="RegexpHeader">
+    <property name="header" value="/\*\n \* Copyright \(c\) (20[0-9][0-9], )?20[0-9][0-9], Oracle and/or its affiliates. All rights reserved.\n \* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n \*\n \* This code is free software; you can redistribute it and/or modify it\n \* under the terms of the GNU General Public License version 2 only, as\n \* published by the Free Software Foundation.\n \*\n \* This code is distributed in the hope that it will be useful, but WITHOUT\n \* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n \* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n \* version 2 for more details \(a copy is included in the LICENSE file that\n \* accompanied this code\).\n \*\n \* You should have received a copy of the GNU General Public License version\n \* 2 along with this work; if not, write to the Free Software Foundation,\n \* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n \*\n \* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n \* or visit www.oracle.com if you need additional information or have any\n \* questions.\n \*/\n"/>
+  </module>
+  <module name="FileTabCharacter">
+    <property name="severity" value="error"/>
+  </module>
+  <module name="NewlineAtEndOfFile">
+    <property name="lineSeparator" value="lf"/>
+  </module>
+  <module name="Translation"/>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="Checkstyle: stop constant name check"/>
+    <property name="onCommentFormat" value="Checkstyle: resume constant name check"/>
+    <property name="checkFormat" value="ConstantNameCheck"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Allow non-conforming constant names"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="Checkstyle: stop method name check"/>
+    <property name="onCommentFormat" value="Checkstyle: resume method name check"/>
+    <property name="checkFormat" value="MethodName"/>
+    <property name="checkC" value="false"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable method name checks"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="CheckStyle: stop parameter assignment check"/>
+    <property name="onCommentFormat" value="CheckStyle: resume parameter assignment check"/>
+    <property name="checkFormat" value="ParameterAssignment"/>
+    <property name="checkC" value="false"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable Parameter Assignment"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="Checkstyle: stop final variable check"/>
+    <property name="onCommentFormat" value="Checkstyle: resume final variable check"/>
+    <property name="checkFormat" value="FinalLocalVariable"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable final variable checks"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="Checkstyle: stop"/>
+    <property name="onCommentFormat" value="Checkstyle: resume"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable all checks"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="// START GENERATED RAW ASSEMBLER METHODS"/>
+    <property name="onCommentFormat" value="// END GENERATED RAW ASSEMBLER METHODS"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable all checks for generated raw assembler methods"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="// START GENERATED LABEL ASSEMBLER METHODS"/>
+    <property name="onCommentFormat" value="// END GENERATED LABEL ASSEMBLER METHODS"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable all checks for generated label assembler methods"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="CheckStyle: stop inner assignment check"/>
+    <property name="onCommentFormat" value="CheckStyle: resume inner assignment check"/>
+    <property name="checkFormat" value="InnerAssignment"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable inner assignment checks"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="Checkstyle: stop field name check"/>
+    <property name="onCommentFormat" value="Checkstyle: resume field name check"/>
+    <property name="checkFormat" value="MemberName"/>
+    <property name="checkC" value="false"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable field name checks"/>
+  </module>
+</module>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/.classpath	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.asm"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.base"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.asmdis"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.cri"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.graal.compiler"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.graal.graph"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/.project	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>com.oracle.max.graal.examples</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>net.sourceforge.metrics.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>net.sf.eclipsecs.core.CheckstyleBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>net.sourceforge.metrics.nature</nature>
+		<nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
+	</natures>
+</projectDescription>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/.settings/org.eclipse.jdt.core.prefs	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,384 @@
+#Sat Jan 22 17:02:08 CET 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.builder.cleanOutputFolder=clean
+org.eclipse.jdt.core.builder.duplicateResourceTask=warning
+org.eclipse.jdt.core.builder.invalidClasspath=abort
+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
+org.eclipse.jdt.core.circularClasspath=error
+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
+org.eclipse.jdt.core.codeComplete.argumentPrefixes=
+org.eclipse.jdt.core.codeComplete.argumentSuffixes=
+org.eclipse.jdt.core.codeComplete.fieldPrefixes=
+org.eclipse.jdt.core.codeComplete.fieldSuffixes=
+org.eclipse.jdt.core.codeComplete.localPrefixes=
+org.eclipse.jdt.core.codeComplete.localSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=ignore
+org.eclipse.jdt.core.compiler.problem.deadCode=ignore
+org.eclipse.jdt.core.compiler.problem.deprecation=error
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=enabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=error
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=ignore
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=error
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=ignore
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=error
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=enabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=enabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=error
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=disabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nullReference=ignore
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+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.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=error
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unsafeTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=ignore
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.taskCaseSensitive=enabled
+org.eclipse.jdt.core.compiler.taskPriorities=NORMAL,HIGH,NORMAL
+org.eclipse.jdt.core.compiler.taskTags=TODO,FIXME,XXX
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=48
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=1
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=true
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert
+org.eclipse.jdt.core.formatter.comment.line_length=120
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=4
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=4
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
+org.eclipse.jdt.core.formatter.indentation.size=8
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=true
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=200
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=true
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=true
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=space
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=true
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=false
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
+org.eclipse.jdt.core.incompatibleJDKLevel=error
+org.eclipse.jdt.core.incompleteClasspath=error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/.settings/org.eclipse.jdt.ui.prefs	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,75 @@
+#Fri Jul 23 17:15:05 PDT 2010
+comment_clear_blank_lines=false
+comment_format_comments=true
+comment_format_header=true
+comment_format_html=true
+comment_format_source_code=true
+comment_indent_parameter_description=true
+comment_indent_root_tags=true
+comment_line_length=120
+comment_new_line_for_parameter=true
+comment_separate_root_tags=true
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_MaxineJavaCodeStyle2
+formatter_settings_version=11
+org.eclipse.jdt.ui.exception.name=e
+org.eclipse.jdt.ui.gettersetter.use.is=true
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=java;javax;org;com;
+org.eclipse.jdt.ui.javadoc=false
+org.eclipse.jdt.ui.keywordthis=false
+org.eclipse.jdt.ui.ondemandthreshold=0
+org.eclipse.jdt.ui.overrideannotation=true
+org.eclipse.jdt.ui.staticondemandthreshold=0
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\n * @return Returns the ${bare_field_name}.\n */</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template><template autoinsert\="true" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">${filecomment}\n${package_declaration}\n\n${typecomment}\n${type_declaration}</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\n *\n * @author ${user}\n */</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment">/**\n * \n */</template><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">// ${todo} Auto-generated catch block\n${exception_var}.printStackTrace();</template><template autoinsert\="false" context\="filecomment_context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment">/*\n * Copyright (c) 2007 Sun Microsystems, Inc.  All rights reserved.\n *\n * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product\n * that is described in this document. In particular, and without limitation, these intellectual property\n * rights may include one or more of the U.S. patents listed at http\://www.sun.com/patents and one or\n * more additional patents or pending patent applications in the U.S. and in other countries.\n *\n * U.S. Government Rights - Commercial software. Government users are subject to the Sun\n * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its\n * supplements.\n *\n * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or\n * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks\n * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the\n * U.S. and other countries.\n *\n * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open\n * Company, Ltd.\n */\n</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">// ${todo} Auto-generated method stub\n${body_statement}</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment">/**\n * @param ${param} The ${bare_field_name} to set.\n */</template><template autoinsert\="true" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment">/* (non-Javadoc)\n * ${see_to_overridden}\n */</template><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\n * ${tags}\n * ${see_to_target}\n */</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\n</template></templates>
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=false
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=false
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.make_local_variable_final=false
+sp_cleanup.make_parameters_final=false
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_variable_declarations_final=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=false
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=false
+sp_cleanup.remove_unnecessary_nls_tags=false
+sp_cleanup.remove_unused_imports=false
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=false
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=false
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/bin/META-INF/services/com.oracle.max.graal.extensions.FrameModifier	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,1 @@
+com.oracle.max.graal.examples.deopt.FrameModifierImpl
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/bin/META-INF/services/com.oracle.max.graal.extensions.InliningGuide	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,1 @@
+com.oracle.max.graal.examples.inlining.InliningGuideImpl
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/bin/META-INF/services/com.oracle.max.graal.extensions.Intrinsifier	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,1 @@
+com.oracle.max.graal.examples.intrinsics.IntrinsifierImpl
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/bin/META-INF/services/com.oracle.max.graal.extensions.Optimizer	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,1 @@
+com.oracle.max.graal.examples.opt.OptimizerImpl
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/create_examples.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<project default="create_run_jar" name="Create Runnable Jar for Project com.oracle.max.graal.examples">
+    <!--this file was created by Eclipse Runnable JAR Export Wizard-->
+    <!--ANT 1.7 is required                                        -->
+    <target name="create_run_jar">
+        <jar destfile="./examples.jar" filesetmanifest="mergewithoutmain">
+            <manifest>
+                <attribute name="Main-Class" value="com.oracle.max.graal.examples.Main"/>
+                <attribute name="Class-Path" value="."/>
+            </manifest>
+            <fileset dir="bin"/>
+        </jar>
+    </target>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/runexample.sh	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,23 @@
+#!/bin/bash
+if [ -z "${JDK7}" ]; then
+  echo "JDK7 is not defined."
+  exit 1;
+fi
+if [ -z "${MAXINE}" ]; then
+  echo "MAXINE is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${GRAAL}" ]; then
+  echo "GRAAL is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${DACAPO}" ]; then
+  echo "DACAPO is not defined. It must point to a Dacapo benchmark directory."
+  exit 1;
+fi
+TEST=$1
+shift
+ant -f create_examples.xml
+COMMAND="${JDK7}/bin/java -client -d64 -graal -Xmx1g -esa -ea -G:Extend -G:CacheGraphs -XX:+PrintCompilation -Xcomp -XX:CompileOnly=examples -XX:CompileCommand=quiet -XX:CompileCommand=exclude,*,<init> -XX:CompileCommand=exclude,*,<clinit> -XX:CompileCommand=exclude,*,run -XX:CompileCommand=exclude,com.oracle.max.graal.examples.Main::main $* -jar examples.jar ${TEST}"
+# echo $COMMAND
+$COMMAND
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/runexample_c1.sh	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,23 @@
+#!/bin/bash
+if [ -z "${JDK7}" ]; then
+  echo "JDK7 is not defined."
+  exit 1;
+fi
+if [ -z "${MAXINE}" ]; then
+  echo "MAXINE is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${GRAAL}" ]; then
+  echo "GRAAL is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${DACAPO}" ]; then
+  echo "DACAPO is not defined. It must point to a Dacapo benchmark directory."
+  exit 1;
+fi
+TEST=$1
+shift
+ant -f create_examples.xml
+COMMAND="${JDK7G}/bin/java -client -d64 -Xmx1g -esa -XX:+PrintCFGToFile -XX:+PrintCompilation -Xcomp -XX:CompileOnly=examples -XX:CompileCommand=quiet -XX:CompileCommand=exclude,*,<init> -XX:CompileCommand=exclude,*,run -XX:CompileCommand=exclude,com.oracle.max.graal.examples.Main::main $* -jar examples.jar ${TEST}"
+# echo $COMMAND
+$COMMAND
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/runexample_c2.sh	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,23 @@
+#!/bin/bash
+if [ -z "${JDK7}" ]; then
+  echo "JDK7 is not defined."
+  exit 1;
+fi
+if [ -z "${MAXINE}" ]; then
+  echo "MAXINE is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${GRAAL}" ]; then
+  echo "GRAAL is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${DACAPO}" ]; then
+  echo "DACAPO is not defined. It must point to a Dacapo benchmark directory."
+  exit 1;
+fi
+TEST=$1
+shift
+ant -f create_examples.xml
+COMMAND="${JDK7G}/bin/java -d64 -Xmx1g -esa -XX:+PrintCompilation -XX:PrintIdealGraphLevel=1 -Xcomp -XX:CompileOnly=examples -XX:CompileCommand=quiet -XX:CompileCommand=exclude,*,<init> -XX:CompileCommand=exclude,*,run -XX:CompileCommand=exclude,com.oracle.max.graal.examples.Main::main $* -jar examples.jar ${TEST}"
+# echo $COMMAND
+$COMMAND
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/runexamplescompare.sh	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,29 @@
+#!/bin/bash
+if [ -z "${JDK7}" ]; then
+  echo "JDK7 is not defined."
+  exit 1;
+fi
+if [ -z "${MAXINE}" ]; then
+  echo "MAXINE is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${GRAAL}" ]; then
+  echo "GRAAL is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${DACAPO}" ]; then
+  echo "DACAPO is not defined. It must point to a Dacapo benchmark directory."
+  exit 1;
+fi
+TEST=$1
+shift
+ant -f create_examples.xml
+COMMAND="${JDK7}/bin/java -client -d64 -graal -Xms1g -Xmx2g -esa -G:Extend -Xcomp -XX:CompileOnly=examples $* -jar examples.jar ${TEST}"
+echo $COMMAND
+$COMMAND
+COMMAND="${JDK7}/bin/java -client -d64 -Xms1g -Xmx2g -esa -Xcomp -XX:CompileOnly=examples $* -jar examples.jar ${TEST}"
+echo $COMMAND
+$COMMAND
+COMMAND="${JDK7}/bin/java -server -d64 -Xms1g -Xmx2g -esa -Xcomp -XX:CompileOnly=examples $* -jar examples.jar ${TEST}"
+echo $COMMAND
+$COMMAND
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/META-INF/services/com.oracle.max.graal.extensions.FrameModifier	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,1 @@
+com.oracle.max.graal.examples.deopt.FrameModifierImpl
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/META-INF/services/com.oracle.max.graal.extensions.InliningGuide	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,1 @@
+com.oracle.max.graal.examples.inlining.InliningGuideImpl
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/META-INF/services/com.oracle.max.graal.extensions.Intrinsifier	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,1 @@
+com.oracle.max.graal.examples.intrinsics.IntrinsifierImpl
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/META-INF/services/com.oracle.max.graal.extensions.Optimizer	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,1 @@
+com.oracle.max.graal.examples.opt.OptimizerImpl
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/Main.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.examples;
+
+import com.oracle.max.graal.examples.deopt.*;
+import com.oracle.max.graal.examples.inlining.*;
+import com.oracle.max.graal.examples.intrinsics.*;
+import com.oracle.max.graal.examples.opt.*;
+import com.oracle.max.graal.examples.simple.*;
+
+public class Main {
+
+    public static void main(String[] args) {
+        System.err.println("== Graal Examples ==");
+        if (args.length == 1) {
+            if (args[0].equals("simple")) {
+                SimpleExample.run();
+            } else if (args[0].equals("inlining")) {
+                InliningExample.run();
+            } else if (args[0].equals("safeadd")) {
+                SafeAddExample.run();
+            } else if (args[0].equals("opt")) {
+                OptimizationExample.run();
+            } else if (args[0].equals("deopt")) {
+                DeoptExample.run();
+            } else {
+                System.out.println("unknown example: " + args[0]);
+            }
+        } else {
+            System.out.println("usage: java " + Main.class.getSimpleName() + " <example>");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/deopt/DeoptExample.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.examples.deopt;
+
+import com.oracle.max.graal.examples.intrinsics.*;
+
+
+public class DeoptExample {
+
+    public static void run() {
+        System.out.println();
+        System.out.println();
+        System.out.println("Running Deopt Example");
+        long start = System.currentTimeMillis();
+        System.out.println("result1=" + new DeoptExample().test());
+        System.out.println("time=" + (System.currentTimeMillis() - start) + "ms");
+    }
+
+    private int test() {
+        try {
+            return testDeopt(90000);
+        } catch (IllegalStateException e) {
+            System.out.println(e.getMessage());
+            return 0;
+        }
+    }
+
+    private int testDeopt(int n) {
+        int sum = 0;
+        for (int i = 0; i < n; i = SafeAddExample.safeAdd(i, 1)) {
+            sum = SafeAddExample.safeAdd(sum, i);
+        }
+        return sum;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/deopt/DeoptHandler.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.examples.deopt;
+
+import java.lang.reflect.*;
+
+import com.sun.cri.ri.*;
+
+
+public class DeoptHandler {
+
+    /**
+     * Deoptimization handler method for methods with a void return parameter.
+     */
+    public void handle_void(RiMethod method, int bci, Object[] values, int numLocals, int numStack, int numLocks) {
+        handle(method, bci, values, numLocals, numStack, numLocks);
+    }
+
+    /**
+     * Deoptimization handler method for methods with an int return parameter.
+     */
+    public int handle_int(RiMethod method, int bci, Object[] values, int numLocals, int numStack, int numLocks) {
+        handle(method, bci, values, numLocals, numStack, numLocks);
+        return 123;
+    }
+
+    /**
+     * Deoptimization handler method for methods with an object return parameter.
+     */
+    public Object handle_object(RiMethod method, int bci, Object[] values, int numLocals, int numStack, int numLocks) {
+        handle(method, bci, values, numLocals, numStack, numLocks);
+        return null;
+    }
+
+    /**
+     * Deoptimization handler method: prints the current state of the method execution.
+     */
+    public int handle(RiMethod method, int bci, Object[] values, int numLocals, int numStack, int numLocks) {
+        System.out.printf("Deoptimization: %s@%d", method.name(), bci);
+        int p = 0;
+        System.out.print("\nArguments: ");
+        int argCount = method.signature().argumentCount(!Modifier.isStatic(method.accessFlags()));
+        for (int i = 0; i < argCount; i++) {
+            System.out.printf("%s ", values[p++]);
+        }
+        System.out.print("\nLocals: ");
+        for (int i = argCount; i < numLocals; i++) {
+            System.out.printf("%s ", values[p++]);
+        }
+        System.out.print("\nExpression stack: ");
+        for (int i = 0; i < numStack; i++) {
+            System.out.printf("%s ", values[p++]);
+        }
+        System.out.print("\nLocks: ");
+        for (int i = 0; i < numLocks; i++) {
+            System.out.printf("%s ", values[p++]);
+        }
+        System.out.println();
+        return 2;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/deopt/FrameModifierImpl.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.examples.deopt;
+
+import java.util.*;
+
+import com.oracle.max.graal.extensions.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ci.CiVirtualObject.*;
+import com.sun.cri.ri.*;
+
+
+public class FrameModifierImpl implements FrameModifier {
+    private static DeoptHandler HANDLER = new DeoptHandler();
+
+    @Override
+    public CiFrame getFrame(RiRuntime runtime, CiFrame frame) {
+        if (frame.method.name().equals("testDeopt")) {
+            // get the handler method
+            RiType type = runtime.getType(DeoptHandler.class);
+            CiKind returnKind = frame.method.signature().returnKind();
+            String methodName = "handle_" + returnKind;
+            String methodSignature = "(Lcom/sun/cri/ri/RiMethod;I[Ljava/lang/Object;III)" + returnKind.signatureChar();
+            RiMethod handlerMethod = type.getMethod(methodName, methodSignature);
+            assert handlerMethod != null : methodName + " not found...";
+
+            // put the current state (local vars, expressions, etc.) into an array
+            CiVirtualObjectFactory factory = new CiVirtualObjectFactory(runtime);
+            ArrayList<CiValue> originalValues = new ArrayList<CiValue>();
+            for (int i = 0; i < frame.values.length; i += frame.values[i].kind.sizeInSlots()) {
+                originalValues.add(factory.proxy(frame.values[i]));
+            }
+            CiValue boxedValues = factory.arrayProxy(runtime.getType(Object[].class), originalValues.toArray(new CiValue[originalValues.size()]));
+
+            // build the list of arguments
+            CiValue[] newValues = new CiValue[handlerMethod.maxLocals()];
+            int p = 0;
+            newValues[p++] = CiConstant.forObject(HANDLER);         // receiver
+            newValues[p++] = CiConstant.forObject(frame.method);    // method that caused deoptimization
+            newValues[p++] = CiConstant.forInt(frame.bci);          // bytecode index
+            newValues[p++] = boxedValues;                           // original locals, expression stack and locks
+            newValues[p++] = CiConstant.forInt(frame.numLocals);    // number of locals
+            newValues[p++] = CiConstant.forInt(frame.numStack);     // size of expression stack
+            newValues[p++] = CiConstant.forInt(frame.numLocks);     // number of locks
+
+            // fill the rest of the local variables with zeros
+            while (p < newValues.length) {
+                newValues[p++] = CiValue.IllegalValue;
+            }
+
+            // ... and return a new frame that points to the start of the handler method
+            return new CiFrame((CiFrame) frame.caller, handlerMethod, /*bci*/ 0, false, newValues, handlerMethod.maxLocals(), 0, 0);
+        }
+        return frame;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/inlining/InliningExample.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.examples.inlining;
+
+
+public class InliningExample {
+
+    public static void run() {
+        System.out.println();
+        System.out.println();
+        System.out.println("Running Inlining Example");
+        long start = System.currentTimeMillis();
+        System.out.println("result1=" + test());
+        System.out.println("result2=" + testFib());
+        System.out.println("time=" + (System.currentTimeMillis() - start) + "ms");
+    }
+
+    private static int test() {
+        return alwaysInline(30);
+    }
+
+    public static int testFib() {
+        int sum = 0;
+        for (int i = 0; i < 100000000; ++i) {
+            sum += fib(5);
+        }
+        return sum;
+    }
+
+    public static int alwaysInline(int value) {
+        if (value == 0) {
+            return neverInline(value);
+        }
+        return alwaysInline(value - 1);
+    }
+
+    public static int neverInline(int value) {
+        if (value == 0) {
+            return 0;
+        }
+        return neverInline(value - 1);
+    }
+
+    public static int fib(int val) {
+        if (val == 0 || val == 1) {
+            return 1;
+        }
+        return fib(val - 1) + fib(val - 2);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/inlining/InliningGuideImpl.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.examples.inlining;
+
+import com.oracle.max.graal.extensions.*;
+import com.sun.cri.ri.*;
+
+
+public class InliningGuideImpl implements InliningGuide {
+
+    @Override
+    public InliningHint getHint(int depth, RiMethod caller, int bci, RiMethod target) {
+        if (target.name().equals("neverInline")) {
+            return InliningHint.NEVER;
+        } else if (target.name().equals("alwaysInline") && depth < 50) {
+            return InliningHint.ALWAYS;
+        } else if (target.name().equals("fib") && depth < 5) {
+            return InliningHint.ALWAYS;
+        }
+        return InliningHint.NONE;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/intrinsics/IntrinsifierImpl.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.examples.intrinsics;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.graph.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.extensions.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+
+public class IntrinsifierImpl implements Intrinsifier {
+
+    @Override
+    public Graph intrinsicGraph(RiRuntime runtime, RiMethod caller, int bci, RiMethod method, List<? extends Node> parameters) {
+        if (method.holder().name().equals("Lcom/oracle/max/graal/examples/intrinsics/SafeAddExample;") && method.name().equals("safeAdd")) {
+            CompilerGraph graph = new CompilerGraph(runtime);
+            Return returnNode = new Return(new SafeAddNode(new Local(CiKind.Long, 0, graph), new Local(CiKind.Long, 1, graph), graph), graph);
+            graph.start().setNext(returnNode);
+            graph.setReturn(returnNode);
+            return graph;
+        }
+        return null;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/intrinsics/SafeAddExample.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.examples.intrinsics;
+
+
+public class SafeAddExample {
+
+    public static final int N = 100000000;
+
+    public static void run() {
+        System.out.println();
+        System.out.println();
+        System.out.println("Running SafeAdd Example");
+        long start = System.currentTimeMillis();
+        System.out.println("result=" + testSafeAdd());
+        System.out.println("time=" + (System.currentTimeMillis() - start) + "ms");
+    }
+
+    private static int testSafeAdd() {
+        int sum = 0;
+        int j = N;
+        for (int i = -N; i < N; ++i) {
+            sum = safeAdd(sum, i);
+            sum = safeAdd(sum, j);
+            --j;
+        }
+        return sum;
+    }
+
+    public static int safeAdd(int a, int b) {
+        int result = a + b;
+        if (b < 0 && result > a) {
+            throw new IllegalStateException("underflow when adding " + a + " and " + b);
+        } else if (b > 0 && result < a) {
+            throw new IllegalStateException("overflow when adding " + a + " and " + b);
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/intrinsics/SafeAddNode.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.examples.intrinsics;
+
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+
+public final class SafeAddNode extends IntegerArithmeticNode {
+    public SafeAddNode(Value x, Value y, Graph graph) {
+        super(CiKind.Int, Bytecodes.LADD, x, y, graph);
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new SafeAddNode(null, null, into);
+    }
+
+    @Override
+    public String shortName() {
+        return "[+]";
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return (T) GENERATOR_OP;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static final LIRGenerator.LIRGeneratorOp GENERATOR_OP = new LIRGenerator.LIRGeneratorOp() {
+        @Override
+        public void generate(Node n, LIRGenerator generator) {
+            SafeAddNode add = (SafeAddNode) n;
+            generator.integerAdd(add, add.x(), add.y());
+            generator.deoptimizeOn(Condition.OF);
+        }
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/opt/OptimizationExample.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.examples.opt;
+
+import com.oracle.max.graal.examples.intrinsics.*;
+
+
+public class OptimizationExample {
+
+    public static void run() {
+        System.out.println();
+        System.out.println();
+        System.out.println("Running Optimization Example");
+        long start = System.currentTimeMillis();
+        System.out.println("result=" + test(1000000000));
+        System.out.println("time=" + (System.currentTimeMillis() - start) + "ms");
+    }
+
+    private static long test(int n) {
+        long sum = 0;
+        for (int i = 0; i < n; i = SafeAddExample.safeAdd(i, 1)) {
+            sum = sum + i;
+        }
+        return sum;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/opt/OptimizerImpl.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.examples.opt;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.examples.intrinsics.*;
+import com.oracle.max.graal.extensions.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+
+public class OptimizerImpl implements Optimizer {
+
+    @Override
+    public void optimize(RiRuntime runtime, Graph graph) {
+        // iterate over all instanceof of SafeAddNode in the graph
+        for (SafeAddNode safeAdd : graph.getNodes(SafeAddNode.class)) {
+            if (!canOverflow(safeAdd)) {
+                // if an overflow is impossible: replace with normal add
+                IntegerAdd add = new IntegerAdd(CiKind.Int, safeAdd.x(), safeAdd.y(), graph);
+                safeAdd.replaceAndDelete(add);
+            }
+        }
+    }
+
+    private boolean canOverflow(SafeAddNode safeAdd) {
+        // if this SafeAddNode always adds 1 ...
+        if (safeAdd.y().isConstant() && safeAdd.y().asConstant().asLong() == 1) {
+            // ... to a phi ...
+            if (safeAdd.x() instanceof Phi) {
+                Phi phi = (Phi) safeAdd.x();
+                // ... that belongs to a loop and merges into itself ...
+                if (phi.merge() instanceof LoopBegin && phi.valueAt(1) == safeAdd) {
+                    LoopBegin loopBegin = (LoopBegin) phi.merge();
+                    // ... then do the heavy analysis.
+                    return canOverflow(phi, loopBegin);
+                }
+            }
+        }
+        return true;
+    }
+
+    private boolean canOverflow(Phi phi, LoopBegin loopBegin) {
+        NodeBitMap nodes = LoopUtil.markUpCFG(loopBegin);
+        NodeBitMap exits = LoopUtil.computeLoopExits(loopBegin, nodes);
+        // look at all loop exits:
+        for (Node exit : exits) {
+            TTY.println("exit: " + exit);
+            Node pred = exit.predecessors().get(0);
+            // if this exit is an If node ...
+            if (pred instanceof If) {
+                If ifNode = (If) pred;
+                // ... which compares ...
+                if (ifNode.compare() instanceof Compare) {
+                    Compare compare = (Compare) ifNode.compare();
+                    Condition cond = compare.condition();
+                    Value x = compare.x();
+                    Value y = compare.y();
+                    if (ifNode.trueSuccessor() == pred) {
+                        cond = cond.negate();
+                    }
+                    // ... the phi against a value, then this phi cannot overflow.
+                    if (cond == Condition.LT && x == phi) {
+                        return false;
+                    }
+                    if (cond == Condition.GT && y == phi) {
+                        return false;
+                    }
+                }
+            }
+        }
+        TTY.println("can overflow");
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/simple/SimpleExample.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.examples.simple;
+
+
+public class SimpleExample {
+
+    public static void run() {
+        System.out.println(mulAdd(1, 2, 3));
+        System.out.println(divAdd(1, 2, 3));
+    }
+
+    private static int mulAdd(int a, int b, int c) {
+        return a * b + c;
+    }
+
+    private static int divAdd(int a, int b, int c) {
+        return a / b + c;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.graphviz/.checkstyle	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<fileset-config file-format-version="1.2.0" simple-config="true" sync-formatter="false">
+  <local-check-config name="C1X Checkstyle checks" location="/com.oracle.max.graal.compiler/.checkstyle_checks.xml" type="project" description="">
+    <additional-data name="protect-config-file" value="false"/>
+  </local-check-config>
+  <fileset name="all" enabled="true" check-config-name="C1X Checkstyle checks" local="true">
+    <file-match-pattern match-pattern="." include-pattern="true"/>
+  </fileset>
+</fileset-config>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.graphviz/.classpath	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="test"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.graal.graph"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.graphviz/.project	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>com.oracle.max.graal.graphviz</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>net.sf.eclipsecs.core.CheckstyleBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
+	</natures>
+</projectDescription>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.graphviz/.settings/org.eclipse.jdt.core.prefs	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,270 @@
+#Wed Apr 27 22:10:44 CEST 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=1
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=true
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=120
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=4
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=4
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
+org.eclipse.jdt.core.formatter.indentation.size=8
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=true
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=200
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=true
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=true
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=space
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=false
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.graphviz/.settings/org.eclipse.jdt.ui.prefs	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,4 @@
+#Wed Apr 27 22:10:44 CEST 2011
+eclipse.preferences.version=1
+formatter_profile=_C1XJavaCodeStyle
+formatter_settings_version=11
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.graphviz/src/com/oracle/max/graal/graphviz/GraphvizPrinter.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.graphviz;
+
+import java.awt.Color;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.util.HashMap;
+import java.util.HashSet;
+
+import com.oracle.max.graal.graph.Graph;
+import com.oracle.max.graal.graph.Node;
+import com.oracle.max.graal.graph.NodeArray;
+
+/**
+ * Generates a representation of {@link Node Nodes} or entire {@link Graph Graphs} in the DOT language that can be
+ * visualized with <a href="http://www.graphviz.org/">Graphviz</a>.
+ */
+public class GraphvizPrinter {
+
+    public static final Color NODE_BGCOLOR = Color.WHITE;
+    private static final String NODE_BGCOLOR_STRING = formatColorString(NODE_BGCOLOR);
+
+    private static String formatColorString(Color c) {
+        return String.format("#%02x%02x%02x%02x", c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
+    }
+
+    private final PrintStream out;
+    private final HashSet<Class<?>> omittedClasses = new HashSet<Class<?>>();
+    private final HashMap<Class<?>, String> classColors = new HashMap<Class<?>, String>();
+
+    /**
+     * Creates a new {@link GraphvizPrinter} that writes to the specified output stream.
+     */
+    public GraphvizPrinter(OutputStream out) {
+        this.out = new PrintStream(out);
+    }
+
+    public void addOmittedClass(Class<?> clazz) {
+        omittedClasses.add(clazz);
+    }
+
+    public void addClassColor(Class<?> clazz, String color) {
+        classColors.put(clazz, color);
+    }
+
+    /**
+     * Opens a graph with the specified title (label). Call this before printing any nodes, but not more than once
+     * without calling {@link #end()} first.
+     * 
+     * @param title
+     *            The graph's label.
+     */
+    public void begin(String title) {
+        out.println("digraph g {");
+        if (title != null) {
+            out.println("  label=\"" + title + "\";");
+        }
+    }
+
+    /**
+     * Closes the graph. No nodes should be printed afterwards. Another graph can be opened with {@link #begin(String)},
+     * but many Graphviz output plugins ignore additional graphs in their input.
+     */
+    public void end() {
+        out.println("}");
+    }
+
+    /**
+     * Prints all nodes and edges in the specified graph.
+     */
+    public void print(Graph graph, boolean shortNames) {
+        // graph.getNodes() returns all the graph's nodes, not just "roots"
+        for (Node n : graph.getNodes()) {
+            printNode(n, shortNames);
+        }
+    }
+
+    /**
+     * Prints a single node and edges for all its inputs and successors.
+     */
+    public void printNode(Node node, boolean shortNames) {
+        if (omittedClasses.contains(node.getClass())) {
+            return;
+        }
+        int id = node.id();
+        String name = "n" + id;
+        NodeArray inputs = node.inputs();
+        NodeArray successors = node.successors();
+
+        String color = classColors.get(node.getClass());
+
+        if (shortNames) {
+            printNode(name, node.id(), excapeLabel(node.shortName()), color, inputs.size(), successors.size());
+        } else {
+            printNode(name, node.id(), excapeLabel(node.toString()), color, inputs.size(), successors.size());
+        }
+
+        for (int i = 0; i < successors.size(); ++i) {
+            Node successor = successors.get(i);
+            if (successor != Node.Null && !omittedClasses.contains(successor.getClass())) {
+                printControlEdge(id, i, successor.id());
+            }
+        }
+
+        for (int i = 0; i < inputs.size(); ++i) {
+            Node input = inputs.get(i);
+            if (input != Node.Null && !omittedClasses.contains(input.getClass())) {
+                if (node.getClass().getSimpleName().equals("FrameState") && input.getClass().getSimpleName().equals("Local")) {
+                    continue;
+                }
+                printDataEdge(id, i, input.id());
+            }
+        }
+    }
+
+    private void printNode(String name, Number number, String label, String color, int ninputs, int nsuccessors) {
+        int minWidth = Math.min(1 + label.length() / 3, 10);
+        minWidth = Math.max(minWidth, Math.max(ninputs + 1, nsuccessors + 1));
+        out.println(name + "  [shape=plaintext,");
+        out.println("   label=< <TABLE BORDER=\"0\" CELLSPACING=\"0\"><TR>");
+
+        printPort("predecessors", "rosybrown1");
+
+        for (int i = 1; i < minWidth - ninputs; i++) {
+            printEmptyPort();
+        }
+
+        for (int i = 0; i < ninputs; i++) {
+            printPort("in" + i, "lightgrey");
+        }
+
+        if (number != null) {
+            label = "<FONT POINT-SIZE=\"8\">" + number + "</FONT> " + label;
+        }
+
+        out.println("    </TR><TR><TD BORDER=\"1\" COLSPAN=\"" + minWidth + "\" BGCOLOR=\"" + (color != null ? color : NODE_BGCOLOR_STRING) + "\">" + label + "</TD></TR><TR>");
+
+        for (int i = 0; i < nsuccessors; i++) {
+            printPort("succ" + i, "rosybrown1");
+        }
+
+        for (int i = 1; i < minWidth - nsuccessors; i++) {
+            printEmptyPort();
+        }
+
+        printPort("usages", "lightgrey");
+
+        out.println("    </TR></TABLE>>]; ");
+    }
+
+    private static String excapeLabel(String label) {
+        label = label.replace("&", "&amp;");
+        label = label.replace("<", "&lt;");
+        label = label.replace(">", "&gt;");
+        label = label.replace("\"", "&quot;");
+        return label;
+    }
+
+    private void printPort(String name, String color) {
+        out.print("    <TD CELLPADDING=\"0\" WIDTH=\"15\"><TABLE BORDER=\"0\" CELLSPACING=\"2\" CELLPADDING=\"0\"><TR><TD WIDTH=\"15\" HEIGHT=\"5\" PORT=\"");
+        out.print(name);
+        out.print("\" BGCOLOR=\"");
+        out.print(color);
+        out.println("\"></TD></TR></TABLE></TD>");
+    }
+
+    private void printEmptyPort() {
+        out.print("    <TD CELLPADDING=\"0\" WIDTH=\"15\"><TABLE BORDER=\"0\" CELLSPACING=\"2\" CELLPADDING=\"0\"><TR><TD WIDTH=\"15\" HEIGHT=\"5\"></TD></TR></TABLE></TD>");
+    }
+
+    private void printControlEdge(int from, int fromPort, int to) {
+        out.println("n" + from + ":succ" + fromPort + ":s -> n" + to + ":predecessors:n [color=red, weight=2];");
+    }
+
+    private void printDataEdge(int from, int fromPort, int to) {
+        out.println("n" + to + ":usages:s -> n" + from + ":in" + fromPort + ":n [color=black,dir=back];");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.graphviz/src/com/oracle/max/graal/graphviz/GraphvizRunner.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.graphviz;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Provides functionality to process graphs in the DOT language with a Graphviz tool and obtain the generated output.
+ */
+public class GraphvizRunner {
+
+    public static final String DOT_LAYOUT = "dot";
+
+    /**
+     * Processes data from an input stream with a Graphviz tool such as {@code dot}, writing output in the specified
+     * format to the given output stream. The method waits for the executed tool to finish and then returns its exit
+     * code.
+     * 
+     * @param layout
+     *            The Graphviz layouter to use (e.g. "dot").
+     * @param in
+     *            Stream to read input from.
+     * @param out
+     *            Stream to write output to.
+     * @param format
+     *            Desired output format (-T parameter).
+     * @return Exit code of the called utility.
+     * @throws IOException
+     *             When the process can not be started (e.g. Graphviz missing) or reading/writing a stream fails.
+     */
+    public static int process(String layout, InputStream in, OutputStream out, String format) throws IOException {
+        byte[] buffer = new byte[4096];
+
+        // create and start process
+        ProcessBuilder pb = new ProcessBuilder("dot", "-T", format, "-K", layout);
+        Process p = pb.start();
+
+        // write data from in to stdin
+        OutputStream stdin = p.getOutputStream();
+        transfer(buffer, in, stdin);
+        stdin.close();
+        in.close();
+
+        // read output from stdout and write to out
+        InputStream stdout = p.getInputStream();
+        transfer(buffer, stdout, out);
+        stdout.close();
+
+        // wait for process to terminate
+        for (;;) {
+            try {
+                return p.waitFor();
+            } catch (InterruptedException e) {
+                // ignore
+            }
+        }
+    }
+
+    /**
+     * Reads all data from an {@link InputStream} and writes it to an {@link OutputStream}, using the provided buffer.
+     */
+    private static void transfer(byte[] buffer, InputStream in, OutputStream out) throws IOException {
+        int count;
+        while ((count = in.read(buffer, 0, buffer.length)) != -1) {
+            out.write(buffer, 0, count);
+        }
+        in.close();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.graphviz/test/com/oracle/graal/graph/vis/GraphvizTest.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2011, 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.vis;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.junit.Test;
+
+import com.oracle.max.graal.graph.Graph;
+import com.oracle.max.graal.graph.Node;
+import com.oracle.max.graal.graphviz.GraphvizPrinter;
+import com.oracle.max.graal.graphviz.GraphvizRunner;
+
+/**
+ * Tests for the Graphviz graph generator. Needs Graphviz (more specifically, dot) installed to verify produced output.
+ */
+public class GraphvizTest {
+
+    @Test
+    public void testSimpleGraph() throws IOException {
+        Graph g = new Graph();
+
+        DummyNode start = new DummyNode("start", 0, 1, g);
+
+        DummyNode ifnode = new DummyNode("if", 2, 2, g);
+        start.setSuccessor(0, ifnode);
+
+        // branch 1
+        DummyNode nop = new DummyNode("nop", 0, 1, g);
+        ifnode.setSuccessor(0, nop);
+
+        // branch 2
+        DummyNode a = new DummyNode("a", 0, 1, g);
+        DummyNode b = new DummyNode("b", 0, 1, g);
+        DummyNode plus = new DummyNode("+", 2, 1, g);
+        plus.setInput(0, a);
+        plus.setInput(1, b);
+        ifnode.setSuccessor(1, plus);
+
+        DummyNode end = new DummyNode("end", 0, 1, g);
+        plus.setSuccessor(0, end);
+        nop.setSuccessor(0, end);
+
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        GraphvizPrinter printer = new GraphvizPrinter(out);
+        printer.begin("Simple test");
+        printer.print(g, false);
+        printer.end();
+
+        int exitCode = GraphvizRunner.process(GraphvizRunner.DOT_LAYOUT, new ByteArrayInputStream(out.toByteArray()), new NullOutputStream(), "xdot");
+        assertEquals(0, exitCode);
+    }
+
+    private static class DummyNode extends Node {
+
+        private final int inputCount;
+        private final int successorCount;
+        private final String name;
+
+        public DummyNode(String name, int inputCount, int successorCount, Graph graph) {
+            super(inputCount, successorCount, graph);
+            this.name = name;
+            this.inputCount = inputCount;
+            this.successorCount = successorCount;
+        }
+
+        @Override
+        public Node copy(Graph into) {
+            return new DummyNode(name, inputCount, successorCount, into);
+        }
+
+        public void setInput(int idx, Node n) {
+            inputs().set(idx, n);
+        }
+
+        public void setSuccessor(int idx, Node n) {
+            successors().set(idx, n);
+        }
+
+        @Override
+        protected int inputCount() {
+            return super.inputCount() + inputCount;
+        }
+
+        @Override
+        protected int successorCount() {
+            return super.inputCount() + successorCount;
+        }
+
+        @Override
+        public String toString() {
+            return name;
+        }
+    }
+
+    private static class NullOutputStream extends OutputStream {
+
+        @Override
+        public void write(int b) throws IOException {
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/.checkstyle	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<fileset-config file-format-version="1.2.0" simple-config="true" sync-formatter="false">
+  <local-check-config name="C1X Checkstyle checks" location=".checkstyle_checks.xml" type="project" description="">
+    <additional-data name="protect-config-file" value="false"/>
+  </local-check-config>
+  <fileset name="all" enabled="true" check-config-name="C1X Checkstyle checks" local="true">
+    <file-match-pattern match-pattern="." include-pattern="true"/>
+  </fileset>
+</fileset-config>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/.checkstyle_checks.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,191 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN" "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
+
+<!--
+    This configuration file was written by the eclipse-cs plugin configuration editor
+-->
+<!--
+    Checkstyle-Configuration: C1X Checkstyle checks
+    Description: none
+-->
+<module name="Checker">
+  <property name="severity" value="warning"/>
+  <module name="TreeWalker">
+    <property name="tabWidth" value="4"/>
+    <module name="FileContentsHolder"/>
+    <module name="JavadocStyle">
+      <property name="checkHtml" value="false"/>
+    </module>
+    <module name="LocalFinalVariableName"/>
+    <module name="LocalVariableName"/>
+    <module name="MemberName">
+      <property name="format" value="^(([a-z][a-zA-Z0-9]*$)|(_[A-Z][a-zA-Z0-9]*_[a-z][a-zA-Z0-9]*$))"/>
+    </module>
+    <module name="MethodName">
+      <property name="format" value="^[a-z][a-z_A-Z0-9]*$"/>
+    </module>
+    <module name="PackageName"/>
+    <module name="ParameterName"/>
+    <module name="TypeName">
+      <property name="format" value="^[A-Z][_a-zA-Z0-9]*$"/>
+    </module>
+    <module name="RedundantImport"/>
+    <module name="LineLength">
+      <property name="max" value="250"/>
+    </module>
+    <module name="MethodParamPad"/>
+    <module name="NoWhitespaceAfter">
+      <property name="tokens" value="ARRAY_INIT,BNOT,DEC,DOT,INC,LNOT,UNARY_MINUS,UNARY_PLUS"/>
+    </module>
+    <module name="NoWhitespaceBefore">
+      <property name="tokens" value="SEMI,DOT,POST_DEC,POST_INC"/>
+    </module>
+    <module name="ParenPad"/>
+    <module name="TypecastParenPad">
+      <property name="tokens" value="RPAREN,TYPECAST"/>
+    </module>
+    <module name="WhitespaceAfter"/>
+    <module name="WhitespaceAround">
+      <property name="tokens" value="ASSIGN,BAND,BAND_ASSIGN,BOR,BOR_ASSIGN,BSR,BSR_ASSIGN,BXOR,BXOR_ASSIGN,COLON,DIV,DIV_ASSIGN,EQUAL,GE,GT,LAND,LE,LITERAL_ASSERT,LITERAL_CATCH,LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_FOR,LITERAL_IF,LITERAL_RETURN,LITERAL_SYNCHRONIZED,LITERAL_TRY,LITERAL_WHILE,LOR,LT,MINUS,MINUS_ASSIGN,MOD,MOD_ASSIGN,NOT_EQUAL,PLUS,PLUS_ASSIGN,QUESTION,SL,SLIST,SL_ASSIGN,SR,SR_ASSIGN,STAR,STAR_ASSIGN,LITERAL_ASSERT,TYPE_EXTENSION_AND"/>
+    </module>
+    <module name="RedundantModifier"/>
+    <module name="AvoidNestedBlocks">
+      <property name="allowInSwitchCase" value="true"/>
+    </module>
+    <module name="EmptyBlock">
+      <property name="option" value="text"/>
+      <property name="tokens" value="LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_IF,LITERAL_TRY,LITERAL_WHILE,STATIC_INIT"/>
+    </module>
+    <module name="LeftCurly"/>
+    <module name="NeedBraces"/>
+    <module name="RightCurly"/>
+    <module name="DoubleCheckedLocking">
+      <property name="severity" value="error"/>
+    </module>
+    <module name="EmptyStatement"/>
+    <module name="HiddenField">
+      <property name="severity" value="ignore"/>
+      <property name="ignoreConstructorParameter" value="true"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="FinalClass"/>
+    <module name="HideUtilityClassConstructor">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="ArrayTypeStyle"/>
+    <module name="UpperEll"/>
+    <module name="FallThrough"/>
+    <module name="FinalLocalVariable">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="MultipleVariableDeclarations"/>
+    <module name="StringLiteralEquality">
+      <property name="severity" value="error"/>
+    </module>
+    <module name="SuperFinalize"/>
+    <module name="UnnecessaryParentheses">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="Indentation">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="StaticVariableName">
+      <property name="format" value="^[A-Za-z][a-zA-Z0-9]*$"/>
+    </module>
+    <module name="EmptyForInitializerPad"/>
+    <module name="EmptyForIteratorPad"/>
+    <module name="ModifierOrder"/>
+    <module name="DefaultComesLast"/>
+    <module name="InnerAssignment">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="JUnitTestCase"/>
+    <module name="ModifiedControlVariable"/>
+    <module name="MutableException"/>
+    <module name="ParameterAssignment">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="RegexpSinglelineJava">
+      <property name="format" value="\s$"/>
+      <property name="message" value="Illegal trailing whitespace(s) at the end of the line."/>
+      <property name="ignoreComments" value="true"/>
+      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Checks for trailing spaces at the end of a line"/>
+    </module>
+    <module name="RegexpSinglelineJava">
+      <property name="format" value=" ,"/>
+      <property name="ignoreComments" value="true"/>
+      <metadata name="com.atlassw.tools.eclipse.checkstyle.customMessage" value="Illegal whitespace before a comma."/>
+      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Checks for whitespace before a comma."/>
+    </module>
+  </module>
+  <module name="RegexpHeader">
+    <property name="header" value="/\*\n \* Copyright \(c\) (20[0-9][0-9], )?20[0-9][0-9], Oracle and/or its affiliates. All rights reserved.\n \* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n \*\n \* This code is free software; you can redistribute it and/or modify it\n \* under the terms of the GNU General Public License version 2 only, as\n \* published by the Free Software Foundation.\n \*\n \* This code is distributed in the hope that it will be useful, but WITHOUT\n \* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n \* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n \* version 2 for more details \(a copy is included in the LICENSE file that\n \* accompanied this code\).\n \*\n \* You should have received a copy of the GNU General Public License version\n \* 2 along with this work; if not, write to the Free Software Foundation,\n \* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n \*\n \* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n \* or visit www.oracle.com if you need additional information or have any\n \* questions.\n \*/\n"/>
+  </module>
+  <module name="FileTabCharacter">
+    <property name="severity" value="error"/>
+  </module>
+  <module name="NewlineAtEndOfFile">
+    <property name="lineSeparator" value="lf"/>
+  </module>
+  <module name="Translation"/>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="Checkstyle: stop constant name check"/>
+    <property name="onCommentFormat" value="Checkstyle: resume constant name check"/>
+    <property name="checkFormat" value="ConstantNameCheck"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Allow non-conforming constant names"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="Checkstyle: stop method name check"/>
+    <property name="onCommentFormat" value="Checkstyle: resume method name check"/>
+    <property name="checkFormat" value="MethodName"/>
+    <property name="checkC" value="false"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable method name checks"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="CheckStyle: stop parameter assignment check"/>
+    <property name="onCommentFormat" value="CheckStyle: resume parameter assignment check"/>
+    <property name="checkFormat" value="ParameterAssignment"/>
+    <property name="checkC" value="false"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable Parameter Assignment"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="Checkstyle: stop final variable check"/>
+    <property name="onCommentFormat" value="Checkstyle: resume final variable check"/>
+    <property name="checkFormat" value="FinalLocalVariable"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable final variable checks"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="Checkstyle: stop"/>
+    <property name="onCommentFormat" value="Checkstyle: resume"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable all checks"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="// START GENERATED RAW ASSEMBLER METHODS"/>
+    <property name="onCommentFormat" value="// END GENERATED RAW ASSEMBLER METHODS"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable all checks for generated raw assembler methods"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="// START GENERATED LABEL ASSEMBLER METHODS"/>
+    <property name="onCommentFormat" value="// END GENERATED LABEL ASSEMBLER METHODS"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable all checks for generated label assembler methods"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="CheckStyle: stop inner assignment check"/>
+    <property name="onCommentFormat" value="CheckStyle: resume inner assignment check"/>
+    <property name="checkFormat" value="InnerAssignment"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable inner assignment checks"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="Checkstyle: stop field name check"/>
+    <property name="onCommentFormat" value="Checkstyle: resume field name check"/>
+    <property name="checkFormat" value="MemberName"/>
+    <property name="checkC" value="false"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable field name checks"/>
+  </module>
+</module>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/.classpath	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.asm"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.base"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.asmdis"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.cri"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.graal.compiler"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.graal.graph"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/.project	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>com.oracle.max.graal.runtime</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>net.sourceforge.metrics.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>net.sf.eclipsecs.core.CheckstyleBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>net.sourceforge.metrics.nature</nature>
+		<nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
+	</natures>
+</projectDescription>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/.settings/org.eclipse.jdt.core.prefs	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,384 @@
+#Sat Jan 22 17:02:08 CET 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.builder.cleanOutputFolder=clean
+org.eclipse.jdt.core.builder.duplicateResourceTask=warning
+org.eclipse.jdt.core.builder.invalidClasspath=abort
+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
+org.eclipse.jdt.core.circularClasspath=error
+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
+org.eclipse.jdt.core.codeComplete.argumentPrefixes=
+org.eclipse.jdt.core.codeComplete.argumentSuffixes=
+org.eclipse.jdt.core.codeComplete.fieldPrefixes=
+org.eclipse.jdt.core.codeComplete.fieldSuffixes=
+org.eclipse.jdt.core.codeComplete.localPrefixes=
+org.eclipse.jdt.core.codeComplete.localSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=ignore
+org.eclipse.jdt.core.compiler.problem.deadCode=ignore
+org.eclipse.jdt.core.compiler.problem.deprecation=error
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=enabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=error
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=ignore
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=error
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=ignore
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=error
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=enabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=enabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=error
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=disabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nullReference=ignore
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+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.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=error
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unsafeTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=ignore
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.taskCaseSensitive=enabled
+org.eclipse.jdt.core.compiler.taskPriorities=NORMAL,HIGH,NORMAL
+org.eclipse.jdt.core.compiler.taskTags=TODO,FIXME,XXX
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=48
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=1
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=true
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert
+org.eclipse.jdt.core.formatter.comment.line_length=120
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=4
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=4
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
+org.eclipse.jdt.core.formatter.indentation.size=8
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=true
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=200
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=true
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=true
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=space
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=true
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=false
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
+org.eclipse.jdt.core.incompatibleJDKLevel=error
+org.eclipse.jdt.core.incompleteClasspath=error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/.settings/org.eclipse.jdt.ui.prefs	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,75 @@
+#Fri Jul 23 17:15:05 PDT 2010
+comment_clear_blank_lines=false
+comment_format_comments=true
+comment_format_header=true
+comment_format_html=true
+comment_format_source_code=true
+comment_indent_parameter_description=true
+comment_indent_root_tags=true
+comment_line_length=120
+comment_new_line_for_parameter=true
+comment_separate_root_tags=true
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_MaxineJavaCodeStyle2
+formatter_settings_version=11
+org.eclipse.jdt.ui.exception.name=e
+org.eclipse.jdt.ui.gettersetter.use.is=true
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=java;javax;org;com;
+org.eclipse.jdt.ui.javadoc=false
+org.eclipse.jdt.ui.keywordthis=false
+org.eclipse.jdt.ui.ondemandthreshold=0
+org.eclipse.jdt.ui.overrideannotation=true
+org.eclipse.jdt.ui.staticondemandthreshold=0
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\n * @return Returns the ${bare_field_name}.\n */</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template><template autoinsert\="true" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">${filecomment}\n${package_declaration}\n\n${typecomment}\n${type_declaration}</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\n *\n * @author ${user}\n */</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment">/**\n * \n */</template><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">// ${todo} Auto-generated catch block\n${exception_var}.printStackTrace();</template><template autoinsert\="false" context\="filecomment_context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment">/*\n * Copyright (c) 2007 Sun Microsystems, Inc.  All rights reserved.\n *\n * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product\n * that is described in this document. In particular, and without limitation, these intellectual property\n * rights may include one or more of the U.S. patents listed at http\://www.sun.com/patents and one or\n * more additional patents or pending patent applications in the U.S. and in other countries.\n *\n * U.S. Government Rights - Commercial software. Government users are subject to the Sun\n * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its\n * supplements.\n *\n * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or\n * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks\n * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the\n * U.S. and other countries.\n *\n * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open\n * Company, Ltd.\n */\n</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">// ${todo} Auto-generated method stub\n${body_statement}</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment">/**\n * @param ${param} The ${bare_field_name} to set.\n */</template><template autoinsert\="true" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment">/* (non-Javadoc)\n * ${see_to_overridden}\n */</template><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\n * ${tags}\n * ${see_to_target}\n */</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\n</template></templates>
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=false
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=false
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.make_local_variable_final=false
+sp_cleanup.make_parameters_final=false
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_variable_declarations_final=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=false
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=false
+sp_cleanup.remove_unnecessary_nls_tags=false
+sp_cleanup.remove_unused_imports=false
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=false
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=false
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/com_sun_hotspot_c1x_VMEntries.h	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,189 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_sun_hotspot_c1x_VMEntries */
+
+#ifndef _Included_com_sun_hotspot_c1x_VMEntries
+#define _Included_com_sun_hotspot_c1x_VMEntries
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class:     com_sun_hotspot_c1x_VMEntries
+ * Method:    RiMethod_code
+ * Signature: (Ljava/lang/Object;)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiMethod_1code
+  (JNIEnv *, jclass, jobject);
+
+/*
+ * Class:     com_sun_hotspot_c1x_VMEntries
+ * Method:    RiMethod_maxStackSize
+ * Signature: (Ljava/lang/Object;)I
+ */
+JNIEXPORT jint JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiMethod_1maxStackSize
+  (JNIEnv *, jclass, jobject);
+
+/*
+ * Class:     com_sun_hotspot_c1x_VMEntries
+ * Method:    RiMethod_maxLocals
+ * Signature: (Ljava/lang/Object;)I
+ */
+JNIEXPORT jint JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiMethod_1maxLocals
+  (JNIEnv *, jclass, jobject);
+
+/*
+ * Class:     com_sun_hotspot_c1x_VMEntries
+ * Method:    RiMethod_holder
+ * Signature: (Ljava/lang/Object;)Lcom/sun/cri/ri/RiType;
+ */
+JNIEXPORT jobject JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiMethod_1holder
+  (JNIEnv *, jclass, jobject);
+
+/*
+ * Class:     com_sun_hotspot_c1x_VMEntries
+ * Method:    RiMethod_signature
+ * Signature: (Ljava/lang/Object;)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiMethod_1signature
+  (JNIEnv *, jclass, jobject);
+
+/*
+ * Class:     com_sun_hotspot_c1x_VMEntries
+ * Method:    RiMethod_name
+ * Signature: (Ljava/lang/Object;)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiMethod_1name
+  (JNIEnv *, jclass, jobject);
+
+/*
+ * Class:     com_sun_hotspot_c1x_VMEntries
+ * Method:    RiSignature_lookupType
+ * Signature: (Ljava/lang/String;Ljava/lang/Object;)Lcom/sun/cri/ri/RiType;
+ */
+JNIEXPORT jobject JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiSignature_1lookupType
+  (JNIEnv *, jclass, jstring, jobject);
+
+/*
+ * Class:     com_sun_hotspot_c1x_VMEntries
+ * Method:    RiSignature_symbolToString
+ * Signature: (Ljava/lang/Object;)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiSignature_1symbolToString
+  (JNIEnv *, jclass, jobject);
+
+/*
+ * Class:     com_sun_hotspot_c1x_VMEntries
+ * Method:    RiType_javaClass
+ * Signature: (Ljava/lang/Object;)Ljava/lang/Class;
+ */
+JNIEXPORT jclass JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiType_1javaClass
+  (JNIEnv *, jclass, jobject);
+
+/*
+ * Class:     com_sun_hotspot_c1x_VMEntries
+ * Method:    RiType_name
+ * Signature: (Ljava/lang/Object;)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiType_1name
+  (JNIEnv *, jclass, jobject);
+
+/*
+ * Class:     com_sun_hotspot_c1x_VMEntries
+ * Method:    RiConstantPool_lookupConstant
+ * Signature: (Ljava/lang/Object;I)Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiConstantPool_1lookupConstant
+  (JNIEnv *, jclass, jobject, jint);
+
+/*
+ * Class:     com_sun_hotspot_c1x_VMEntries
+ * Method:    RiConstantPool_lookupMethod
+ * Signature: (Ljava/lang/Object;IB)Lcom/sun/cri/ri/RiMethod;
+ */
+JNIEXPORT jobject JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiConstantPool_1lookupMethod
+  (JNIEnv *, jclass, jobject, jint, jbyte);
+
+/*
+ * Class:     com_sun_hotspot_c1x_VMEntries
+ * Method:    RiConstantPool_lookupSignature
+ * Signature: (Ljava/lang/Object;I)Lcom/sun/cri/ri/RiSignature;
+ */
+JNIEXPORT jobject JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiConstantPool_1lookupSignature
+  (JNIEnv *, jclass, jobject, jint);
+
+/*
+ * Class:     com_sun_hotspot_c1x_VMEntries
+ * Method:    RiConstantPool_lookupType
+ * Signature: (Ljava/lang/Object;I)Lcom/sun/cri/ri/RiType;
+ */
+JNIEXPORT jobject JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiConstantPool_1lookupType
+  (JNIEnv *, jclass, jobject, jint);
+
+/*
+ * Class:     com_sun_hotspot_c1x_VMEntries
+ * Method:    RiConstantPool_lookupField
+ * Signature: (Ljava/lang/Object;I)Lcom/sun/cri/ri/RiField;
+ */
+JNIEXPORT jobject JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiConstantPool_1lookupField
+  (JNIEnv *, jclass, jobject, jint);
+
+/*
+ * Class:     com_sun_hotspot_c1x_VMEntries
+ * Method:    findRiType
+ * Signature: (Ljava/lang/Object;)Lcom/sun/cri/ri/RiType;
+ */
+JNIEXPORT jobject JNICALL Java_com_sun_hotspot_c1x_VMEntries_findRiType
+  (JNIEnv *, jclass, jobject);
+
+/*
+ * Class:     com_sun_hotspot_c1x_VMEntries
+ * Method:    RiRuntime_getConstantPool
+ * Signature: (Ljava/lang/Object;)Lcom/sun/cri/ri/RiConstantPool;
+ */
+JNIEXPORT jobject JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiRuntime_1getConstantPool
+  (JNIEnv *, jclass, jobject);
+
+/*
+ * Class:     com_sun_hotspot_c1x_VMEntries
+ * Method:    RiType_isArrayClass
+ * Signature: (Ljava/lang/Object;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiType_1isArrayClass
+  (JNIEnv *, jclass, jobject);
+
+/*
+ * Class:     com_sun_hotspot_c1x_VMEntries
+ * Method:    RiType_isInstanceClass
+ * Signature: (Ljava/lang/Object;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiType_1isInstanceClass
+  (JNIEnv *, jclass, jobject);
+
+/*
+ * Class:     com_sun_hotspot_c1x_VMEntries
+ * Method:    RiType_isInterface
+ * Signature: (Ljava/lang/Object;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiType_1isInterface
+  (JNIEnv *, jclass, jobject);
+
+/*
+ * Class:     com_sun_hotspot_c1x_VMEntries
+ * Method:    RiMethod_accessFlags
+ * Signature: (Ljava/lang/Object;)I
+ */
+JNIEXPORT jint JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiMethod_1accessFlags
+  (JNIEnv *, jclass, jobject);
+
+/*
+ * Class:     com_sun_hotspot_c1x_VMEntries
+ * Method:    installCode
+ * Signature: (Ljava/lang/Object;[BI)V
+ */
+JNIEXPORT void JNICALL Java_com_sun_hotspot_c1x_VMEntries_installCode
+  (JNIEnv *, jclass, jobject, jbyteArray, jint);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/create_native_header.bat	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,1 @@
+javah -classpath c1x4hotspot.jar com.sun.hotspot.c1x.VMEntries
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/Compiler.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,36 @@
+/*
+ * 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.max.graal.runtime;
+
+import com.oracle.max.graal.compiler.*;
+import com.sun.cri.ri.*;
+
+public interface Compiler {
+
+    VMEntries getVMEntries();
+    VMExits getVMExits();
+    GraalCompiler getCompiler();
+    RiType lookupType(String returnType, HotSpotTypeResolved accessingClass);
+    HotSpotVMConfig getConfig();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/CompilerImpl.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,201 @@
+/*
+ * 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.max.graal.runtime;
+
+import java.io.*;
+import java.net.*;
+
+import com.oracle.max.asm.target.amd64.*;
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.runtime.logging.*;
+import com.oracle.max.graal.runtime.server.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+import com.sun.cri.xir.*;
+
+/**
+ * Singleton class holding the instance of the GraalCompiler.
+ */
+public final class CompilerImpl implements Compiler, Remote {
+
+    private static Compiler theInstance;
+
+    public static Compiler getInstance() {
+        return theInstance;
+    }
+
+    public static void initialize() {
+        if (theInstance != null) {
+            throw new IllegalStateException("Compiler already initialized");
+        }
+
+        String remote = System.getProperty("graal.remote");
+        if (remote != null) {
+            // remote compilation (will not create a local Compiler)
+            try {
+                System.out.println("Graal compiler started in client/server mode, server: " + remote);
+                Socket socket = new Socket(remote, 1199);
+                ReplacingStreams streams = new ReplacingStreams(socket.getOutputStream(), socket.getInputStream());
+                streams.getInvocation().sendResult(new VMEntriesNative());
+
+                theInstance = (Compiler) streams.getInvocation().waitForResult(false);
+            } catch (IOException e1) {
+                System.out.println("Connection to compilation server FAILED.");
+                throw new RuntimeException(e1);
+            } catch (ClassNotFoundException e2) {
+                System.out.println("Connection to compilation server FAILED.");
+                throw new RuntimeException(e2);
+            }
+        } else {
+            // ordinary local compilation
+            theInstance = new CompilerImpl(null);
+        }
+    }
+
+    public static Compiler initializeServer(VMEntries entries) {
+        assert theInstance == null;
+        theInstance = new CompilerImpl(entries);
+        return theInstance;
+    }
+
+    private final VMEntries vmEntries;
+    private final VMExits vmExits;
+    private GraalCompiler compiler;
+
+    private final HotSpotRuntime runtime;
+    private final CiTarget target;
+    private final RiXirGenerator generator;
+    private final RiRegisterConfig registerConfig;
+    private final HotSpotVMConfig config;
+
+    public HotSpotVMConfig getConfig() {
+        return config;
+    }
+
+    private CompilerImpl(VMEntries entries) {
+
+        // initialize VMEntries
+        if (entries == null) {
+            entries = new VMEntriesNative();
+        }
+
+        // initialize VMExits
+        VMExits exits = new VMExitsNative(this);
+
+        // logging, etc.
+        if (CountingProxy.ENABLED) {
+            exits = CountingProxy.getProxy(VMExits.class, exits);
+            entries = CountingProxy.getProxy(VMEntries.class, entries);
+        }
+        if (Logger.ENABLED) {
+            exits = LoggingProxy.getProxy(VMExits.class, exits);
+            entries = LoggingProxy.getProxy(VMEntries.class, entries);
+        }
+
+        // set the final fields
+        vmEntries = entries;
+        vmExits = exits;
+
+        // initialize compiler and GraalOptions
+        config = vmEntries.getConfiguration();
+        config.check();
+
+        // these options are important - graal will not generate correct code without them
+        GraalOptions.GenSpecialDivChecks = true;
+        GraalOptions.NullCheckUniquePc = true;
+        GraalOptions.InvokeSnippetAfterArguments = true;
+        GraalOptions.StackShadowPages = config.stackShadowPages;
+
+        runtime = new HotSpotRuntime(config, this);
+        registerConfig = runtime.globalStubRegConfig;
+
+        final int wordSize = 8;
+        final int stackFrameAlignment = 16;
+        target = new HotSpotTarget(new AMD64(), true, wordSize, stackFrameAlignment, config.vmPageSize, wordSize, true);
+
+        RiXirGenerator generator = new HotSpotXirGenerator(config, target, registerConfig, this);
+        if (Logger.ENABLED) {
+            this.generator = LoggingProxy.getProxy(RiXirGenerator.class, generator);
+        } else {
+            this.generator = generator;
+        }
+
+    }
+
+    @Override
+    public GraalCompiler getCompiler() {
+        if (compiler == null) {
+            compiler = new GraalCompiler(runtime, target, generator, registerConfig);
+        }
+        return compiler;
+    }
+
+    @Override
+    public VMEntries getVMEntries() {
+        return vmEntries;
+    }
+
+    @Override
+    public VMExits getVMExits() {
+        return vmExits;
+    }
+
+    @Override
+    public RiType lookupType(String returnType, HotSpotTypeResolved accessingClass) {
+        if (returnType.length() == 1 && vmExits instanceof VMExitsNative) {
+            VMExitsNative exitsNative = (VMExitsNative) vmExits;
+            CiKind kind = CiKind.fromPrimitiveOrVoidTypeChar(returnType.charAt(0));
+            switch(kind) {
+                case Boolean:
+                    return exitsNative.typeBoolean;
+                case Byte:
+                    return exitsNative.typeByte;
+                case Char:
+                    return exitsNative.typeChar;
+                case Double:
+                    return exitsNative.typeDouble;
+                case Float:
+                    return exitsNative.typeFloat;
+                case Illegal:
+                    break;
+                case Int:
+                    return exitsNative.typeInt;
+                case Jsr:
+                    break;
+                case Long:
+                    return exitsNative.typeLong;
+                case Object:
+                    break;
+                case Short:
+                    return exitsNative.typeShort;
+                case Void:
+                    return exitsNative.typeVoid;
+                case Word:
+                    break;
+
+            }
+        }
+        return vmEntries.RiSignature_lookupType(returnType, accessingClass);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/CompilerObject.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,38 @@
+/*
+ * 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.max.graal.runtime;
+
+import java.io.*;
+
+
+/**
+ * Parent class for all HotSpot Ri... types.
+ */
+public abstract class CompilerObject implements Serializable {
+    protected final Compiler compiler;
+
+    protected CompilerObject(Compiler compiler) {
+        this.compiler = compiler;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotConstantPool.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,147 @@
+/*
+ * 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.max.graal.runtime;
+
+import java.io.*;
+import java.util.*;
+
+import com.sun.cri.ri.*;
+
+/**
+ * Implementation of RiConstantPool for HotSpot.
+ */
+public class HotSpotConstantPool extends CompilerObject implements RiConstantPool {
+
+    private final long vmId;
+
+    private final FastLRUIntCache<RiMethod> methodCache = new FastLRUIntCache<RiMethod>();
+    private final FastLRUIntCache<RiField> fieldCache = new FastLRUIntCache<RiField>();
+    private final FastLRUIntCache<RiType> typeCache = new FastLRUIntCache<RiType>();
+
+    public static class FastLRUIntCache<T> implements Serializable {
+
+        private static final int InitialCapacity = 4;
+        private int lastKey;
+        private T lastObject;
+
+        private int[] keys;
+        private Object[] objects;
+        private int count;
+
+        @SuppressWarnings("unchecked")
+        private T access(int index) {
+            return (T) objects[index];
+        }
+
+        public T get(int key) {
+            if (key == lastKey) {
+                return lastObject;
+            } else if (count > 1) {
+                for (int i = 0; i < count; ++i) {
+                    if (keys[i] == key) {
+                        lastObject = access(i);
+                        lastKey = key;
+                        return lastObject;
+                    }
+                }
+            }
+            return null;
+        }
+
+        public void add(int key, T object) {
+            count++;
+            if (count == 1) {
+                lastKey = key;
+                lastObject = object;
+            } else {
+                ensureSize();
+                keys[count - 1] = key;
+                objects[count - 1] = object;
+                if (count == 2) {
+                    keys[0] = lastKey;
+                    objects[0] = lastObject;
+                }
+                lastKey = key;
+                lastObject = object;
+            }
+        }
+
+        private void ensureSize() {
+            if (keys == null) {
+                keys = new int[InitialCapacity];
+                objects = new Object[InitialCapacity];
+            } else if (count > keys.length) {
+                keys = Arrays.copyOf(keys, keys.length * 2);
+                objects = Arrays.copyOf(objects, objects.length * 2);
+            }
+        }
+    }
+
+    public HotSpotConstantPool(Compiler compiler, long vmId) {
+        super(compiler);
+        this.vmId = vmId;
+    }
+
+    @Override
+    public Object lookupConstant(int cpi) {
+        Object constant = compiler.getVMEntries().RiConstantPool_lookupConstant(vmId, cpi);
+        return constant;
+    }
+
+    @Override
+    public RiSignature lookupSignature(int cpi) {
+        return compiler.getVMEntries().RiConstantPool_lookupSignature(vmId, cpi);
+    }
+
+    @Override
+    public RiMethod lookupMethod(int cpi, int byteCode) {
+        RiMethod result = methodCache.get(cpi);
+        if (result == null) {
+            result = compiler.getVMEntries().RiConstantPool_lookupMethod(vmId, cpi, (byte) byteCode);
+            methodCache.add(cpi, result);
+        }
+        return result;
+    }
+
+    @Override
+    public RiType lookupType(int cpi, int opcode) {
+        RiType result = typeCache.get(cpi);
+        if (result == null) {
+            result = compiler.getVMEntries().RiConstantPool_lookupType(vmId, cpi);
+            if (result.isResolved()) {
+                typeCache.add(cpi, result);
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public RiField lookupField(int cpi, int opcode) {
+        RiField result = fieldCache.get(cpi);
+        if (result == null) {
+            result = compiler.getVMEntries().RiConstantPool_lookupField(vmId, cpi, (byte) opcode);
+            fieldCache.add(cpi, result);
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotExceptionHandler.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.runtime;
+
+import com.sun.cri.ri.*;
+
+
+public class HotSpotExceptionHandler extends CompilerObject implements RiExceptionHandler {
+    private int startBci;
+    private int endBci;
+    private int handlerBci;
+    private int catchClassIndex;
+    private RiType catchClass;
+
+    public HotSpotExceptionHandler() {
+        super(null);
+    }
+
+    @Override
+    public int startBCI() {
+        return startBci;
+    }
+
+    @Override
+    public int endBCI() {
+        return endBci;
+    }
+
+    @Override
+    public int handlerBCI() {
+        return handlerBci;
+    }
+
+    @Override
+    public int catchTypeCPI() {
+        return catchClassIndex;
+    }
+
+    @Override
+    public boolean isCatchAll() {
+        return catchClassIndex == 0;
+    }
+
+    @Override
+    public RiType catchType() {
+        return catchClass;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotField.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,136 @@
+/*
+ * 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.max.graal.runtime;
+
+import java.lang.reflect.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.sun.cri.ci.CiConstant;
+import com.sun.cri.ci.CiKind;
+import com.sun.cri.ri.RiField;
+import com.sun.cri.ri.RiType;
+
+/**
+ * Represents a field in a HotSpot type.
+ */
+public class HotSpotField extends CompilerObject implements RiField {
+
+    private final RiType holder;
+    private final String name;
+    private final RiType type;
+    private final int offset;
+    private final int accessFlags;
+    private CiConstant constant;
+
+    public HotSpotField(Compiler compiler, RiType holder, String name, RiType type, int offset, int accessFlags) {
+        super(compiler);
+        this.holder = holder;
+        this.name = name;
+        this.type = type;
+        this.offset = offset;
+        this.accessFlags = accessFlags;
+    }
+
+    @Override
+    public int accessFlags() {
+        return accessFlags;
+    }
+
+    @Override
+    public CiConstant constantValue(CiConstant receiver) {
+        if (receiver == null) {
+            if (constant == null && holder.isResolved() && holder.isSubtypeOf(compiler.getVMEntries().getType(GraalOptions.class))) {
+                Field f;
+                try {
+                    f = GraalOptions.class.getField(name);
+                } catch (SecurityException e1) {
+                    return null;
+                } catch (NoSuchFieldException e1) {
+                    return null;
+                }
+                f.setAccessible(true);
+                if (Modifier.isStatic(f.getModifiers())) {
+                    CiKind kind = CiKind.fromJavaClass(f.getType());
+                    Object value;
+                    try {
+                        value = f.get(null);
+                    } catch (IllegalArgumentException e) {
+                        return null;
+                    } catch (IllegalAccessException e) {
+                        return null;
+                    }
+                    constant = CiConstant.forBoxed(kind, value);
+                }
+            }
+
+            // Constant part only valid for static fields.
+            return constant;
+        }
+        return null;
+    }
+
+    @Override
+    public RiType holder() {
+        return holder;
+    }
+
+//    @Override
+//    public boolean equals(Object obj) {
+//        if (obj instanceof HotSpotField) {
+//            HotSpotField other = (HotSpotField) obj;
+//            return other.offset == offset && other.holder.equals(holder());
+//        }
+//        return false;
+//    }
+
+    @Override
+    public boolean isResolved() {
+        return holder.isResolved();
+    }
+
+    @Override
+    public CiKind kind() {
+        return type().kind();
+    }
+
+    @Override
+    public String name() {
+        return name;
+    }
+
+    @Override
+    public RiType type() {
+        return type;
+    }
+
+    public int offset() {
+        return offset;
+    }
+
+    @Override
+    public String toString() {
+        return "HotSpotField<" + holder.name() + "." + name + ":" + offset + ">";
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethod.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,57 @@
+/*
+ * 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.max.graal.runtime;
+
+import java.util.*;
+
+import com.sun.cri.ri.*;
+
+
+public abstract class HotSpotMethod extends CompilerObject implements RiMethod {
+
+    protected RiType holder;
+    protected String name;
+    public Map<Object, Object> compilerStorage;
+
+    protected HotSpotMethod(Compiler compiler) {
+        super(compiler);
+    }
+
+    @Override
+    public final RiType holder() {
+        return holder;
+    }
+
+    @Override
+    public final String name() {
+        return name;
+    }
+
+    @Override
+    public Map<Object, Object> compilerStorage() {
+        if (compilerStorage == null) {
+            compilerStorage = new HashMap<Object, Object>();
+        }
+        return compilerStorage;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodResolved.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,32 @@
+/*
+ * 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.max.graal.runtime;
+
+import com.oracle.max.graal.runtime.server.*;
+import com.sun.cri.ri.*;
+
+public interface HotSpotMethodResolved extends RiMethod, Remote {
+
+    RiMethod uniqueConcreteMethod();
+    void dumpProfile();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodResolvedImpl.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,230 @@
+/*
+ * 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.max.graal.runtime;
+
+import java.lang.reflect.*;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * Implementation of RiMethod for resolved HotSpot methods.
+ */
+public final class HotSpotMethodResolvedImpl extends HotSpotMethod implements HotSpotMethodResolved {
+
+    /** DO NOT USE IN JAVA CODE! */
+    @Deprecated
+    private Object javaMirror;
+
+    // cached values
+    private final int codeSize;
+    private final int accessFlags;
+    private final int maxLocals;
+    private final int maxStackSize;
+    private RiExceptionHandler[] exceptionHandlers;
+    private RiSignature signature;
+    private Boolean hasBalancedMonitors;
+
+    private HotSpotMethodResolvedImpl() {
+        super(null);
+        codeSize = -1;
+        accessFlags = -1;
+        maxLocals = -1;
+        maxStackSize = -1;
+    }
+
+    @Override
+    public int accessFlags() {
+        return accessFlags;
+    }
+
+    @Override
+    public boolean canBeStaticallyBound() {
+        return isLeafMethod() || Modifier.isStatic(accessFlags());
+    }
+
+    @Override
+    public byte[] code() {
+        assert holder.isResolved();
+
+        byte[] ret = compiler.getVMEntries().RiMethod_code(this);
+        assert ret.length == codeSize : "expected: " + codeSize + ", actual: " + ret.length;
+        return ret;
+    }
+
+    @Override
+    public int codeSize() {
+        return codeSize;
+    }
+
+    @Override
+    public RiExceptionHandler[] exceptionHandlers() {
+        return compiler.getVMEntries().RiMethod_exceptionHandlers(this);
+    }
+
+    @Override
+    public boolean hasBalancedMonitors() {
+        if (hasBalancedMonitors == null) {
+            hasBalancedMonitors = compiler.getVMEntries().RiMethod_hasBalancedMonitors(this);
+        }
+        return hasBalancedMonitors;
+    }
+
+    @Override
+    public boolean isClassInitializer() {
+        return "<clinit>".equals(name) && Modifier.isStatic(accessFlags());
+    }
+
+    @Override
+    public boolean isConstructor() {
+        return "<init>".equals(name) && !Modifier.isStatic(accessFlags());
+    }
+
+    @Override
+    public boolean isLeafMethod() {
+        return Modifier.isFinal(accessFlags()) || Modifier.isPrivate(accessFlags());
+    }
+
+    @Override
+    public boolean isOverridden() {
+        throw new UnsupportedOperationException("isOverridden");
+    }
+
+    @Override
+    public boolean noSafepoints() {
+        return false;
+    }
+
+    @Override
+    public boolean isResolved() {
+        return true;
+    }
+
+    @Override
+    public String jniSymbol() {
+        throw new UnsupportedOperationException("jniSymbol");
+    }
+
+    public BitMap[] livenessMap() {
+        return null;
+    }
+
+    @Override
+    public int maxLocals() {
+        return maxLocals;
+    }
+
+    @Override
+    public int maxStackSize() {
+        return maxStackSize;
+    }
+
+    @Override
+    public RiMethodProfile methodData() {
+        return null;
+    }
+
+    @Override
+    public StackTraceElement toStackTraceElement(int bci) {
+        return CiUtil.toStackTraceElement(this, bci);
+    }
+
+    @Override
+    public RiMethod uniqueConcreteMethod() {
+        return compiler.getVMEntries().RiMethod_uniqueConcreteMethod(this);
+    }
+
+    @Override
+    public RiSignature signature() {
+        if (signature == null) {
+            signature = new HotSpotSignature(compiler, compiler.getVMEntries().RiMethod_signature(this));
+        }
+        return signature;
+    }
+
+    @Override
+    public String toString() {
+        return "HotSpotMethod<" + holder().name() + ". " + name + ">";
+    }
+
+    public boolean hasCompiledCode() {
+        // TODO: needs a VMEntries to go cache the result of that method.
+        // This isn't used by GRAAL for now, so this is enough.throwoutCount
+        return false;
+    }
+
+    @Override
+    public RiType accessor() {
+        return null;
+    }
+
+    @Override
+    public int intrinsic() {
+        return 0;
+    }
+
+    @Override
+    public boolean minimalDebugInfo() {
+        return false;
+    }
+
+    public int invocationCount() {
+        return compiler.getVMEntries().RiMethod_invocationCount(this);
+    }
+
+    public int exceptionProbability(int bci) {
+        return compiler.getVMEntries().RiMethod_exceptionProbability(this, bci);
+    }
+
+    public RiTypeProfile typeProfile(int bci) {
+        return compiler.getVMEntries().RiMethod_typeProfile(this, bci);
+    }
+
+    public double branchProbability(int bci) {
+        return compiler.getVMEntries().RiMethod_branchProbability(this, bci);
+    }
+
+    public double[] switchProbability(int bci) {
+        return compiler.getVMEntries().RiMethod_switchProbability(this, bci);
+    }
+
+    public void dumpProfile() {
+        TTY.println("profile info for %s", this);
+        TTY.println("canBeStaticallyBound: " + canBeStaticallyBound());
+        TTY.println("invocationCount: " + invocationCount());
+        for (int i = 0; i < codeSize(); i++) {
+            if (exceptionProbability(i) > 0) {
+                TTY.println("  exceptionProbability@%d: %d", i, exceptionProbability(i));
+            }
+            if (branchProbability(i) != -1) {
+                TTY.println("  branchProbability@%d: %f", i, branchProbability(i));
+            }
+            RiTypeProfile profile = typeProfile(i);
+            if (profile != null && profile.count > 0) {
+                TTY.println("  profile@%d: count: %d, morphism: %d", i, profile.count, profile.morphism);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodUnresolved.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,184 @@
+/*
+ * 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.max.graal.runtime;
+
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * Implementation of RiMethod for unresolved HotSpot methods.
+ */
+public final class HotSpotMethodUnresolved extends HotSpotMethod {
+    private final RiSignature signature;
+
+    public HotSpotMethodUnresolved(Compiler compiler, String name, String signature, RiType holder) {
+        super(compiler);
+        this.name = name;
+        this.holder = holder;
+        this.signature = new HotSpotSignature(compiler, signature);
+    }
+
+    @Override
+    public RiSignature signature() {
+        return signature;
+    }
+
+    @Override
+    public boolean isResolved() {
+        return false;
+    }
+
+    @Override
+    public byte[] code() {
+        throw unresolved("code");
+    }
+
+    @Override
+    public int codeSize() {
+        return 0;
+    }
+
+    @Override
+    public RiMethodProfile methodData() {
+        throw unresolved("methodData");
+    }
+
+    @Override
+    public String jniSymbol() {
+        throw unresolved("jniSymbol");
+    }
+
+    @Override
+    public int maxLocals() {
+        throw unresolved("maxLocals");
+    }
+
+    @Override
+    public int maxStackSize() {
+        throw unresolved("maxStackSize");
+    }
+
+    @Override
+    public boolean hasBalancedMonitors() {
+        throw unresolved("hasBalancedMonitors");
+    }
+
+    @Override
+    public int accessFlags() {
+        throw unresolved("accessFlags");
+    }
+
+    @Override
+    public boolean isLeafMethod() {
+        throw unresolved("isLeafMethod");
+    }
+
+    @Override
+    public boolean isClassInitializer() {
+        return "<clinit>".equals(name);
+    }
+
+    @Override
+    public boolean isConstructor() {
+        return "<init>".equals(name);
+    }
+
+    @Override
+    public boolean isOverridden() {
+        throw unresolved("isOverridden");
+    }
+
+    @Override
+    public boolean noSafepoints() {
+        return false;
+    }
+
+    @Override
+    public BitMap[] livenessMap() {
+        return null;
+    }
+
+    @Override
+    public StackTraceElement toStackTraceElement(int bci) {
+        return CiUtil.toStackTraceElement(this, bci);
+    }
+
+    @Override
+    public boolean canBeStaticallyBound() {
+        throw unresolved("canBeStaticallyBound");
+    }
+
+    @Override
+    public RiExceptionHandler[] exceptionHandlers() {
+        throw unresolved("exceptionHandlers");
+    }
+
+    @Override
+    public boolean minimalDebugInfo() {
+        throw unresolved("minimalDebugInfo");
+    }
+
+    private CiUnresolvedException unresolved(String operation) {
+        return new CiUnresolvedException(operation + " not defined for unresolved method " + name);
+    }
+
+    @Override
+    public String toString() {
+        return "HotSpotMethod<" + holder.name() + ". " + name + ", unresolved>";
+    }
+
+    public boolean hasCompiledCode() {
+        return false;
+    }
+
+    @Override
+    public RiType accessor() {
+        return null;
+    }
+
+    @Override
+    public int intrinsic() {
+        return 0;
+    }
+
+    public int invocationCount() {
+        return -1;
+    }
+
+    public int exceptionProbability(int bci) {
+        return -1;
+    }
+
+    public RiTypeProfile typeProfile(int bci) {
+        return null;
+    }
+
+    public double branchProbability(int bci) {
+        return -1;
+    }
+
+    public double[] switchProbability(int bci) {
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotOptions.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,107 @@
+/*
+ * 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.max.graal.runtime;
+
+import java.lang.reflect.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.runtime.logging.*;
+
+public class HotSpotOptions {
+
+    public static void setDefaultOptions() {
+        GraalOptions.CommentedAssembly = false;
+        GraalOptions.MethodEndBreakpointGuards = 2;
+        GraalOptions.ResolveClassBeforeStaticInvoke = false;
+    }
+
+    public static boolean setOption(String option) {
+        if (option.length() == 0) {
+            return false;
+        }
+
+        Object value = null;
+        String fieldName = null;
+        String valueString = null;
+
+        char first = option.charAt(0);
+        if (first == '+' || first == '-') {
+            fieldName = option.substring(1);
+            value = (first == '+');
+        } else {
+            int index = option.indexOf('=');
+            if (index == -1) {
+                fieldName = option;
+                valueString = null;
+            } else {
+                fieldName = option.substring(0, index);
+                valueString = option.substring(index + 1);
+            }
+        }
+
+        Field f;
+        try {
+            f = GraalOptions.class.getField(fieldName);
+
+            if (value == null) {
+                if (f.getType() == Float.TYPE) {
+                    value = Float.parseFloat(valueString);
+                } else if (f.getType() == Double.TYPE) {
+                    value = Double.parseDouble(valueString);
+                } else if (f.getType() == Integer.TYPE) {
+                    value = Integer.parseInt(valueString);
+                } else if (f.getType() == Boolean.TYPE) {
+                    if (valueString == null || valueString.length() == 0) {
+                        value = true;
+                    } else {
+                        value = Boolean.parseBoolean(valueString);
+                    }
+                } else if (f.getType() == String.class) {
+                    value = valueString;
+                }
+            }
+            if (value != null) {
+                f.set(null, value);
+                //Logger.info("Set option " + fieldName + " to " + value);
+            } else {
+                Logger.info("Wrong value \"" + valueString + "\" for option " + fieldName);
+                return false;
+            }
+        } catch (SecurityException e) {
+            Logger.info("Security exception when setting option " + option);
+            return false;
+        } catch (NoSuchFieldException e) {
+            Logger.info("Could not find option " + fieldName);
+            return false;
+        } catch (IllegalArgumentException e) {
+            Logger.info("Illegal value for option " + option);
+            return false;
+        } catch (IllegalAccessException e) {
+            Logger.info("Illegal access exception when setting option " + option);
+            return false;
+        }
+
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotProxy.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,92 @@
+/*
+ * 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.max.graal.runtime;
+
+/**
+ * Provides methods to classify the HotSpot-internal identifiers.
+ */
+public final class HotSpotProxy {
+
+    private HotSpotProxy() {
+    }
+
+    private enum CompilerObjectType {
+        // this enum needs to have the same values as the one in graal_Compiler.hpp
+        STUB(0x100000000000000L),
+        METHOD(0x200000000000000L),
+        CLASS(0x300000000000000L),
+        SYMBOL(0x400000000000000L),
+        CONSTANT_POOL(0x500000000000000L),
+        CONSTANT(0x600000000000000L),
+        TYPE_MASK(0xf00000000000000L),
+        DUMMY_CONSTANT(0x6ffffffffffffffL);
+
+        public final long bits;
+
+        CompilerObjectType(long bits) {
+            this.bits = bits;
+        }
+    }
+
+    public static final Long DUMMY_CONSTANT_OBJ = CompilerObjectType.DUMMY_CONSTANT.bits;
+
+    private static boolean isType(long id, CompilerObjectType type) {
+        return (id & CompilerObjectType.TYPE_MASK.bits) == type.bits;
+    }
+
+    public static boolean isStub(long id) {
+        return isType(id, CompilerObjectType.STUB);
+    }
+
+    public static boolean isMethod(long id) {
+        return isType(id, CompilerObjectType.METHOD);
+    }
+
+    public static boolean isClass(long id) {
+        return isType(id, CompilerObjectType.CLASS);
+    }
+
+    public static boolean isSymbol(long id) {
+        return isType(id, CompilerObjectType.SYMBOL);
+    }
+
+    public static boolean isConstantPool(long id) {
+        return isType(id, CompilerObjectType.CONSTANT_POOL);
+    }
+
+    public static boolean isConstant(long id) {
+        return isType(id, CompilerObjectType.CONSTANT_POOL);
+    }
+
+    public static String toString(long id) {
+        CompilerObjectType type = null;
+        for (CompilerObjectType t : CompilerObjectType.values()) {
+            if ((id & CompilerObjectType.TYPE_MASK.bits) == t.bits) {
+                type = t;
+            }
+        }
+        long num = id & ~CompilerObjectType.TYPE_MASK.bits;
+        return type + " " + num;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotRegisterConfig.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,209 @@
+/*
+ * 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.max.graal.runtime;
+
+import static com.oracle.max.asm.target.amd64.AMD64.*;
+
+import java.util.*;
+
+import com.oracle.max.asm.target.amd64.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ci.CiCallingConvention.Type;
+import com.sun.cri.ci.CiRegister.RegisterFlag;
+import com.sun.cri.ri.*;
+
+public class HotSpotRegisterConfig implements RiRegisterConfig {
+
+    // be careful - the contents of this array are duplicated in graal_CodeInstaller.cpp
+    private final CiRegister[] allocatable = {
+        rax, rbx, rcx, rdx, rsi, rdi, r8, r9, /* r10, */r11, r12, r13, r14, /*r15*/
+        xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
+        xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
+    };
+
+    private final EnumMap<RegisterFlag, CiRegister[]> categorized = CiRegister.categorize(allocatable);
+
+    private final RiRegisterAttributes[] attributesMap;
+
+    @Override
+    public CiRegister[] getAllocatableRegisters() {
+        return allocatable;
+    }
+
+    @Override
+    public EnumMap<RegisterFlag, CiRegister[]> getCategorizedAllocatableRegisters() {
+        return categorized;
+    }
+
+    @Override
+    public RiRegisterAttributes[] getAttributesMap() {
+        return attributesMap;
+    }
+
+    private final CiRegister[] generalParameterRegisters;
+    private final CiRegister[] xmmParameterRegisters = {xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7};
+    private final CiRegister[] allParameterRegisters;
+
+    private final CiRegister[] rsaRegs = {
+        rax,  rcx,  rdx,   rbx,   rsp,   rbp,   rsi,   rdi,
+        r8,   r9,   r10,   r11,   r12,   r13,   r14,   r15,
+        xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
+        xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
+    };
+
+    private final CiCalleeSaveLayout registerSaveArea;
+
+
+    public HotSpotRegisterConfig(HotSpotVMConfig config, boolean globalStubConfig) {
+        if (config.windowsOs) {
+            generalParameterRegisters = new CiRegister[] {rdx, r8, r9, rdi, rsi, rcx};
+        } else {
+            generalParameterRegisters = new CiRegister[] {rsi, rdx, rcx, r8, r9, rdi};
+        }
+
+        if (globalStubConfig) {
+            registerSaveArea = new CiCalleeSaveLayout(0, -1, 8, rsaRegs);
+        } else {
+            registerSaveArea = new CiCalleeSaveLayout(0, 0, 0, new CiRegister[0]);
+        }
+
+        attributesMap = RiRegisterAttributes.createMap(this, AMD64.allRegisters);
+        allParameterRegisters = Arrays.copyOf(generalParameterRegisters, generalParameterRegisters.length + xmmParameterRegisters.length);
+        System.arraycopy(xmmParameterRegisters, 0, allParameterRegisters, generalParameterRegisters.length, xmmParameterRegisters.length);
+    }
+
+    @Override
+    public CiRegister[] getCallerSaveRegisters() {
+        return getAllocatableRegisters();
+    }
+
+    @Override
+    public CiRegister getRegisterForRole(int index) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public CiCallingConvention getCallingConvention(Type type, CiKind[] parameters, CiTarget target, boolean stackOnly) {
+        if (type == Type.NativeCall) {
+            throw new UnsupportedOperationException();
+        }
+        return callingConvention(parameters, type, target, stackOnly);
+    }
+
+    public CiRegister[] getCallingConventionRegisters(Type type, RegisterFlag flag) {
+        return allParameterRegisters;
+    }
+
+    private CiCallingConvention callingConvention(CiKind[] types, Type type, CiTarget target, boolean stackOnly) {
+        CiValue[] locations = new CiValue[types.length];
+
+        int currentGeneral = 0;
+        int currentXMM = 0;
+        int currentStackIndex = 0;
+
+        for (int i = 0; i < types.length; i++) {
+            final CiKind kind = types[i];
+
+            switch (kind) {
+                case Byte:
+                case Boolean:
+                case Short:
+                case Char:
+                case Int:
+                case Long:
+                case Word:
+                case Object:
+                    if (!stackOnly && currentGeneral < generalParameterRegisters.length) {
+                        CiRegister register = generalParameterRegisters[currentGeneral++];
+                        locations[i] = register.asValue(kind);
+                    }
+                    break;
+                case Float:
+                case Double:
+                    if (!stackOnly && currentXMM < xmmParameterRegisters.length) {
+                        CiRegister register = xmmParameterRegisters[currentXMM++];
+                        locations[i] = register.asValue(kind);
+                    }
+                    break;
+                default:
+                    throw Util.shouldNotReachHere();
+            }
+
+            if (locations[i] == null) {
+                // we need to adjust for the frame pointer stored on the stack, which shifts incoming arguments by one slot
+                locations[i] = CiStackSlot.get(kind.stackKind(), currentStackIndex + (type.out ? 0 : 1), !type.out);
+                currentStackIndex += target.spillSlots(kind);
+            }
+        }
+
+        return new CiCallingConvention(locations, currentStackIndex * target.spillSlotSize);
+    }
+
+    @Override
+    public CiRegister getReturnRegister(CiKind kind) {
+        switch (kind) {
+            case Boolean:
+            case Byte:
+            case Char:
+            case Short:
+            case Int:
+            case Long:
+            case Object:
+            case Word:
+                return rax;
+            case Float:
+            case Double:
+                return xmm0;
+            case Void:
+            case Illegal:
+                return null;
+            default:
+                throw new UnsupportedOperationException("no return register for type " + kind);
+        }
+    }
+
+    @Override
+    public CiRegister getScratchRegister() {
+        return r10;
+    }
+
+    @Override
+    public CiRegister getFrameRegister() {
+        return rsp;
+    }
+
+    public CiCalleeSaveLayout getCalleeSaveLayout() {
+        return registerSaveArea;
+    }
+
+    @Override
+    public String toString() {
+        String res = String.format(
+             "Allocatable: " + Arrays.toString(getAllocatableRegisters()) + "%n" +
+             "CallerSave:  " + Arrays.toString(getCallerSaveRegisters()) + "%n" +
+             "CalleeSave:  " + getCalleeSaveLayout() + "%n" +
+             "Scratch:     " + getScratchRegister() + "%n");
+        return res;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotRuntime.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,534 @@
+/*
+ * 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.max.graal.runtime;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.graph.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.value.*;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.runtime.nodes.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ci.CiTargetMethod.Call;
+import com.sun.cri.ci.CiTargetMethod.DataPatch;
+import com.sun.cri.ci.CiTargetMethod.Safepoint;
+import com.sun.cri.ri.*;
+import com.sun.cri.ri.RiType.Representation;
+import com.sun.max.asm.dis.*;
+import com.sun.max.lang.*;
+
+/**
+ * CRI runtime implementation for the HotSpot VM.
+ */
+public class HotSpotRuntime implements RiRuntime {
+
+    final HotSpotVMConfig config;
+    final HotSpotRegisterConfig regConfig;
+    final HotSpotRegisterConfig globalStubRegConfig;
+    private final Compiler compiler;
+    private IdentityHashMap<RiMethod, CompilerGraph> intrinsicGraphs = new IdentityHashMap<RiMethod, CompilerGraph>();
+
+
+    public HotSpotRuntime(HotSpotVMConfig config, Compiler compiler) {
+        this.config = config;
+        this.compiler = compiler;
+        regConfig = new HotSpotRegisterConfig(config, false);
+        globalStubRegConfig = new HotSpotRegisterConfig(config, true);
+    }
+
+    @Override
+    public int codeOffset() {
+        return 0;
+    }
+
+    @Override
+    public String disassemble(byte[] code, long address) {
+        return disassemble(code, new DisassemblyPrinter(false), address);
+    }
+
+    private String disassemble(byte[] code, DisassemblyPrinter disassemblyPrinter, long address) {
+        final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+        final ISA instructionSet = ISA.AMD64;
+        Disassembler.disassemble(byteArrayOutputStream, code, instructionSet, WordWidth.BITS_64, address, null, disassemblyPrinter);
+        return byteArrayOutputStream.toString();
+    }
+
+    @Override
+    public String disassemble(final CiTargetMethod targetMethod) {
+
+        final DisassemblyPrinter disassemblyPrinter = new DisassemblyPrinter(false) {
+
+            private String toString(Call call) {
+                if (call.runtimeCall != null) {
+                    return "{" + call.runtimeCall.name() + "}";
+                } else if (call.symbol != null) {
+                    return "{" + call.symbol + "}";
+                } else if (call.stubID != null) {
+                    return "{" + call.stubID + "}";
+                } else {
+                    return "{" + call.method + "}";
+                }
+            }
+
+            private String siteInfo(int pcOffset) {
+                for (Call call : targetMethod.directCalls) {
+                    if (call.pcOffset == pcOffset) {
+                        return toString(call);
+                    }
+                }
+                for (Call call : targetMethod.indirectCalls) {
+                    if (call.pcOffset == pcOffset) {
+                        return toString(call);
+                    }
+                }
+                for (Safepoint site : targetMethod.safepoints) {
+                    if (site.pcOffset == pcOffset) {
+                        return "{safepoint}";
+                    }
+                }
+                for (DataPatch site : targetMethod.dataReferences) {
+                    if (site.pcOffset == pcOffset) {
+                        return "{" + site.constant + "}";
+                    }
+                }
+                return null;
+            }
+
+            @Override
+            protected String disassembledObjectString(Disassembler disassembler, DisassembledObject disassembledObject) {
+                final String string = super.disassembledObjectString(disassembler, disassembledObject);
+
+                String site = siteInfo(disassembledObject.startPosition());
+                if (site != null) {
+                    return string + " " + site;
+                }
+                return string;
+            }
+        };
+        final byte[] code = Arrays.copyOf(targetMethod.targetCode(), targetMethod.targetCodeSize());
+        return disassemble(code, disassemblyPrinter, 0L);
+    }
+
+    @Override
+    public String disassemble(RiMethod method) {
+        return "No disassembler available";
+    }
+
+    @Override
+    public RiConstantPool getConstantPool(RiMethod method) {
+        return ((HotSpotTypeResolved) method.holder()).constantPool();
+    }
+
+    public Class<?> getJavaClass(CiConstant c) {
+        return null;
+    }
+
+    @Override
+    public RiType asRiType(CiKind kind) {
+        return compiler.getVMEntries().getType(kind.toJavaClass());
+    }
+
+    @Override
+    public RiType getTypeOf(CiConstant constant) {
+        return compiler.getVMEntries().getRiType(constant);
+    }
+
+    @Override
+    public boolean isExceptionType(RiType type) {
+        return type.isSubtypeOf(compiler.getVMEntries().getType(Throwable.class));
+    }
+
+    @Override
+    public RiSnippets getSnippets() {
+        throw new UnsupportedOperationException("getSnippets");
+    }
+
+    @Override
+    public boolean mustInline(RiMethod method) {
+        return false;
+    }
+
+    @Override
+    public boolean mustNotCompile(RiMethod method) {
+        return false;
+    }
+
+    @Override
+    public boolean mustNotInline(RiMethod method) {
+        return Modifier.isNative(method.accessFlags());
+    }
+
+    @Override
+    public Object registerCompilerStub(CiTargetMethod targetMethod, String name) {
+        return HotSpotTargetMethod.installStub(compiler, targetMethod, name);
+    }
+
+    @Override
+    public int sizeOfBasicObjectLock() {
+        // TODO shouldn't be hard coded
+        return 2 * 8;
+    }
+
+    @Override
+    public int basicObjectLockOffsetInBytes() {
+        return 8;
+    }
+
+    @Override
+    public CiConstant invoke(RiMethod method, CiMethodInvokeArguments args) {
+        return null;
+    }
+
+    @Override
+    public CiConstant foldWordOperation(int opcode, CiMethodInvokeArguments args) {
+        throw new UnsupportedOperationException("foldWordOperation");
+    }
+
+    @Override
+    public boolean areConstantObjectsEqual(CiConstant x, CiConstant y) {
+        return compiler.getVMEntries().compareConstantObjects(x, y);
+    }
+
+    @Override
+    public RiRegisterConfig getRegisterConfig(RiMethod method) {
+        return regConfig;
+    }
+
+    /**
+     * HotSpots needs an area suitable for storing a program counter for temporary use during the deoptimization process.
+     */
+    @Override
+    public int getCustomStackAreaSize() {
+        return 8;
+    }
+
+    @Override
+    public boolean supportsArrayIntrinsics() {
+        return true;
+    }
+
+    @Override
+    public int getArrayLength(CiConstant array) {
+        return compiler.getVMEntries().getArrayLength(array);
+    }
+
+    @Override
+    public Class<?> asJavaClass(CiConstant c) {
+        return null;
+    }
+
+    @Override
+    public Object asJavaObject(CiConstant c) {
+        return null;
+    }
+
+    @Override
+    public void lower(Node n, CiLoweringTool tool) {
+        if (!GraalOptions.Lower) {
+            return;
+        }
+
+        if (n instanceof LoadField) {
+            LoadField field = (LoadField) n;
+            if (field.isVolatile()) {
+                return;
+            }
+            Graph graph = field.graph();
+            int displacement = ((HotSpotField) field.field()).offset();
+            assert field.kind != CiKind.Illegal;
+            ReadNode memoryRead = new ReadNode(field.field().kind().stackKind(), field.object(), LocationNode.create(field.field(), field.field().kind(), displacement, graph), graph);
+            memoryRead.setGuard((GuardNode) tool.createGuard(new IsNonNull(field.object(), graph)));
+            memoryRead.setNext(field.next());
+            field.replaceAndDelete(memoryRead);
+        } else if (n instanceof StoreField) {
+            StoreField field = (StoreField) n;
+            if (field.isVolatile()) {
+                return;
+            }
+            Graph graph = field.graph();
+            int displacement = ((HotSpotField) field.field()).offset();
+            WriteNode memoryWrite = new WriteNode(CiKind.Illegal, field.object(), field.value(), LocationNode.create(field.field(), field.field().kind(), displacement, graph), graph);
+            memoryWrite.setGuard((GuardNode) tool.createGuard(new IsNonNull(field.object(), graph)));
+            memoryWrite.setStateAfter(field.stateAfter());
+            memoryWrite.setNext(field.next());
+            if (field.field().kind() == CiKind.Object && !field.value().isNullConstant()) {
+                FieldWriteBarrier writeBarrier = new FieldWriteBarrier(field.object(), graph);
+                memoryWrite.setNext(writeBarrier);
+                writeBarrier.setNext(field.next());
+            } else {
+                memoryWrite.setNext(field.next());
+            }
+            field.replaceAndDelete(memoryWrite);
+        } else if (n instanceof LoadIndexed) {
+            LoadIndexed loadIndexed = (LoadIndexed) n;
+            Graph graph = loadIndexed.graph();
+            GuardNode boundsCheck = createBoundsCheck(loadIndexed, tool);
+
+            CiKind elementKind = loadIndexed.elementKind();
+            LocationNode arrayLocation = createArrayLocation(graph, elementKind);
+            arrayLocation.setIndex(loadIndexed.index());
+            ReadNode memoryRead = new ReadNode(elementKind.stackKind(), loadIndexed.array(), arrayLocation, graph);
+            memoryRead.setGuard(boundsCheck);
+            memoryRead.setNext(loadIndexed.next());
+            loadIndexed.replaceAndDelete(memoryRead);
+        } else if (n instanceof StoreIndexed) {
+            StoreIndexed storeIndexed = (StoreIndexed) n;
+            Graph graph = storeIndexed.graph();
+            Anchor anchor = new Anchor(graph);
+            GuardNode boundsCheck = createBoundsCheck(storeIndexed, tool);
+            anchor.addGuard(boundsCheck);
+
+
+            CiKind elementKind = storeIndexed.elementKind();
+            LocationNode arrayLocation = createArrayLocation(graph, elementKind);
+            arrayLocation.setIndex(storeIndexed.index());
+            Value value = storeIndexed.value();
+            Value array = storeIndexed.array();
+            if (elementKind == CiKind.Object && !value.isNullConstant()) {
+                // Store check!
+                if (array.exactType() != null) {
+                    RiType elementType = array.exactType().componentType();
+                    if (elementType.superType() != null) {
+                        Constant type = new Constant(elementType.getEncoding(Representation.ObjectHub), graph);
+                        value = new CheckCast(type, value, graph);
+                    } else {
+                        assert elementType.name().equals("Ljava/lang/Object;") : elementType.name();
+                    }
+                } else {
+                    ReadNode arrayElementKlass = readArrayElementKlass(graph, array);
+                    value = new CheckCast(arrayElementKlass, value, graph);
+                }
+            }
+            WriteNode memoryWrite = new WriteNode(elementKind.stackKind(), array, value, arrayLocation, graph);
+            memoryWrite.setGuard(boundsCheck);
+            memoryWrite.setStateAfter(storeIndexed.stateAfter());
+            anchor.setNext(memoryWrite);
+            if (elementKind == CiKind.Object && !value.isNullConstant()) {
+                ArrayWriteBarrier writeBarrier = new ArrayWriteBarrier(array, arrayLocation, graph);
+                memoryWrite.setNext(writeBarrier);
+                writeBarrier.setNext(storeIndexed.next());
+            } else {
+                memoryWrite.setNext(storeIndexed.next());
+            }
+            storeIndexed.replaceAtPredecessors(anchor);
+            storeIndexed.delete();
+        }
+    }
+
+    private ReadNode readArrayElementKlass(Graph graph, Value array) {
+        ReadNode arrayKlass = readHub(graph, array);
+        ReadNode arrayElementKlass = new ReadNode(CiKind.Object, arrayKlass, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.arrayClassElementOffset, graph), graph);
+        return arrayElementKlass;
+    }
+
+    private LocationNode createArrayLocation(Graph graph, CiKind elementKind) {
+        return LocationNode.create(LocationNode.getArrayLocation(elementKind), elementKind, config.getArrayOffset(elementKind), graph);
+    }
+
+    private GuardNode createBoundsCheck(AccessIndexed n, CiLoweringTool tool) {
+        return (GuardNode) tool.createGuard(new Compare(n.index(), Condition.BT, n.length(), n.graph()));
+    }
+
+    @Override
+    public Graph intrinsicGraph(RiMethod caller, int bci, RiMethod method, List<? extends Node> parameters) {
+        if (!intrinsicGraphs.containsKey(method)) {
+            RiType holder = method.holder();
+            String fullName = method.name() + method.signature().asString();
+            String holderName = holder.name();
+            if (holderName.equals("Ljava/lang/Object;")) {
+                if (fullName.equals("getClass()Ljava/lang/Class;")) {
+                    CompilerGraph graph = new CompilerGraph(this);
+                    Local receiver = new Local(CiKind.Object, 0, graph);
+                    ReadNode klassOop = readHub(graph, receiver);
+                    Return ret = new Return(new ReadNode(CiKind.Object, klassOop, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.classMirrorOffset, graph), graph), graph);
+                    graph.start().setNext(ret);
+                    graph.setReturn(ret);
+                    intrinsicGraphs.put(method, graph);
+                }
+            } else if (holderName.equals("Ljava/lang/System;")) {
+                if (fullName.equals("arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V")) {
+                    CompilerGraph graph = new CompilerGraph(this);
+                    Local src = new Local(CiKind.Object, 0, graph);
+                    Local srcPos = new Local(CiKind.Int, 1, graph);
+                    Local dest = new Local(CiKind.Object, 2, graph);
+                    Local destPos = new Local(CiKind.Int, 3, graph);
+                    Value length = new Local(CiKind.Int, 4, graph);
+                    src.setDeclaredType(((Value) parameters.get(0)).declaredType());
+                    dest.setDeclaredType(((Value) parameters.get(2)).declaredType());
+
+                    if (src.declaredType() == null || dest.declaredType() == null) {
+                        return null;
+                    }
+
+                    if (src.declaredType() != dest.declaredType()) {
+                        return null;
+                    }
+
+                    if (!src.declaredType().isArrayClass()) {
+                        return null;
+                    }
+
+                    CiKind componentType = src.declaredType().componentType().kind();
+                    if (componentType == CiKind.Object) {
+                        return null;
+                    }
+
+                    FrameState stateBefore = new FrameState(method, FrameState.BEFORE_BCI, 0, 0, 0, false, graph);
+                    FrameState stateAfter = new FrameState(method, FrameState.AFTER_BCI, 0, 0, 0, false, graph);
+
+                    // Add preconditions.
+                    FixedGuard guard = new FixedGuard(graph);
+                    ArrayLength srcLength = new ArrayLength(src, graph);
+                    ArrayLength destLength = new ArrayLength(dest, graph);
+                    IntegerAdd upperLimitSrc = new IntegerAdd(CiKind.Int, srcPos, length, graph);
+                    IntegerAdd upperLimitDest = new IntegerAdd(CiKind.Int, destPos, length, graph);
+                    guard.addNode(new Compare(srcPos, Condition.BE, srcLength, graph));
+                    guard.addNode(new Compare(destPos, Condition.BE, destLength, graph));
+                    guard.addNode(new Compare(length, Condition.GE, Constant.forInt(0, graph), graph));
+                    guard.addNode(new Compare(upperLimitSrc, Condition.LE, srcLength, graph));
+                    guard.addNode(new Compare(upperLimitDest, Condition.LE, destLength, graph));
+                    graph.start().setNext(guard);
+
+                    LocationNode location = LocationNode.create(LocationNode.FINAL_LOCATION, componentType, config.getArrayOffset(componentType), graph);
+
+                    // Build normal vector instruction.
+                    CreateVectorNode normalVector = new CreateVectorNode(false, length, graph);
+                    ReadVectorNode values = new ReadVectorNode(new IntegerAddVectorNode(normalVector, srcPos, graph), src, location, graph);
+                    new WriteVectorNode(new IntegerAddVectorNode(normalVector, destPos, graph), dest, location, values, graph);
+                    normalVector.setStateAfter(stateAfter);
+
+                    // Build reverse vector instruction.
+                    CreateVectorNode reverseVector = new CreateVectorNode(true, length, graph);
+                    ReadVectorNode reverseValues = new ReadVectorNode(new IntegerAddVectorNode(reverseVector, srcPos, graph), src, location, graph);
+                    new WriteVectorNode(new IntegerAddVectorNode(reverseVector, destPos, graph), dest, location, reverseValues, graph);
+                    reverseVector.setStateAfter(stateAfter);
+
+                    If ifNode = new If(new Compare(src, Condition.EQ, dest, graph), 0.5, graph);
+                    guard.setNext(ifNode);
+
+                    If secondIf = new If(new Compare(srcPos, Condition.LT, destPos, graph), 0.5, graph);
+                    ifNode.setTrueSuccessor(secondIf);
+
+                    secondIf.setTrueSuccessor(reverseVector);
+
+                    Merge merge1 = new Merge(graph);
+                    merge1.addEnd(new EndNode(graph));
+                    merge1.addEnd(new EndNode(graph));
+                    merge1.setStateAfter(stateBefore);
+
+
+                    Invoke newInvoke = null;
+                    if (componentType == CiKind.Object) {
+                        Value srcClass = readHub(graph, src);
+                        Value destClass = readHub(graph, dest);
+                        If elementClassIf = new If(new Compare(srcClass, Condition.EQ, destClass, graph), 0.5, graph);
+                        ifNode.setFalseSuccessor(elementClassIf);
+                        newInvoke = new Invoke(bci, Bytecodes.INVOKESTATIC, CiKind.Void, new Value[]{src, srcPos, dest, destPos, length}, method, method.signature().returnType(method.holder()), graph);
+                        newInvoke.setCanInline(false);
+                        newInvoke.setStateAfter(stateAfter);
+                        elementClassIf.setFalseSuccessor(newInvoke);
+                        elementClassIf.setTrueSuccessor(merge1.endAt(0));
+                    } else {
+                        ifNode.setFalseSuccessor(merge1.endAt(0));
+                    }
+
+                    secondIf.setFalseSuccessor(merge1.endAt(1));
+                    merge1.setNext(normalVector);
+
+                    Merge merge2 = new Merge(graph);
+                    merge2.addEnd(new EndNode(graph));
+                    merge2.addEnd(new EndNode(graph));
+                    merge2.setStateAfter(stateAfter);
+
+                    normalVector.setNext(merge2.endAt(0));
+                    reverseVector.setNext(merge2.endAt(1));
+
+                    if (newInvoke != null) {
+                        merge2.addEnd(new EndNode(graph));
+                        newInvoke.setNext(merge2.endAt(2));
+                    }
+
+                    Return ret = new Return(null, graph);
+                    merge2.setNext(ret);
+                    graph.setReturn(ret);
+                    return graph;
+                }
+            } else if (holderName.equals("Ljava/lang/Float;")) {
+                if (fullName.equals("floatToRawIntBits(F)I") || fullName.equals("floatToIntBits(F)I")) {
+                    CompilerGraph graph = new CompilerGraph(this);
+                    Return ret = new Return(new FPConversionNode(CiKind.Int, new Local(CiKind.Float, 0, graph), graph), graph);
+                    graph.start().setNext(ret);
+                    graph.setReturn(ret);
+                    intrinsicGraphs.put(method, graph);
+                } else if (fullName.equals("intBitsToFloat(I)F")) {
+                    CompilerGraph graph = new CompilerGraph(this);
+                    Return ret = new Return(new FPConversionNode(CiKind.Float, new Local(CiKind.Int, 0, graph), graph), graph);
+                    graph.start().setNext(ret);
+                    graph.setReturn(ret);
+                    intrinsicGraphs.put(method, graph);
+                }
+            } else if (holderName.equals("Ljava/lang/Double;")) {
+                if (fullName.equals("doubleToRawLongBits(D)J") || fullName.equals("doubleToLongBits(D)J")) {
+                    CompilerGraph graph = new CompilerGraph(this);
+                    Return ret = new Return(new FPConversionNode(CiKind.Long, new Local(CiKind.Double, 0, graph), graph), graph);
+                    graph.start().setNext(ret);
+                    graph.setReturn(ret);
+                    intrinsicGraphs.put(method, graph);
+                } else if (fullName.equals("longBitsToDouble(J)D")) {
+                    CompilerGraph graph = new CompilerGraph(this);
+                    Return ret = new Return(new FPConversionNode(CiKind.Double, new Local(CiKind.Long, 0, graph), graph), graph);
+                    graph.start().setNext(ret);
+                    graph.setReturn(ret);
+                    intrinsicGraphs.put(method, graph);
+                }
+            } else if (holderName.equals("Ljava/lang/Thread;")) {
+                if (fullName.equals("currentThread()Ljava/lang/Thread;")) {
+                    CompilerGraph graph = new CompilerGraph(this);
+                    Return ret = new Return(new CurrentThread(config.threadObjectOffset, graph), graph);
+                    graph.start().setNext(ret);
+                    graph.setReturn(ret);
+                    intrinsicGraphs.put(method, graph);
+                }
+            }
+
+            if (!intrinsicGraphs.containsKey(method)) {
+                intrinsicGraphs.put(method, null);
+            }
+        }
+        return intrinsicGraphs.get(method);
+    }
+
+    private ReadNode readHub(Graph graph, Value value) {
+        return new ReadNode(CiKind.Object, value, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.hubOffset, graph), graph);
+    }
+
+    @Override
+    public RiType getType(Class<?> clazz) {
+        return compiler.getVMEntries().getType(clazz);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotSignature.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,149 @@
+/*
+ * 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.max.graal.runtime;
+
+import java.util.*;
+
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * Represents a method signature.
+ */
+public class HotSpotSignature extends CompilerObject implements RiSignature {
+
+    private final List<String> arguments = new ArrayList<String>();
+    private final String returnType;
+    private final String originalString;
+    private RiType[] argumentTypes;
+    private RiType returnTypeCache;
+
+    public HotSpotSignature(Compiler compiler, String signature) {
+        super(compiler);
+        assert signature.length() > 0;
+        this.originalString = signature;
+
+        if (signature.charAt(0) == '(') {
+            int cur = 1;
+            while (cur < signature.length() && signature.charAt(cur) != ')') {
+                int nextCur = parseSignature(signature, cur);
+                arguments.add(signature.substring(cur, nextCur));
+                cur = nextCur;
+            }
+
+            cur++;
+            int nextCur = parseSignature(signature, cur);
+            returnType = signature.substring(cur, nextCur);
+            assert nextCur == signature.length();
+        } else {
+            returnType = null;
+        }
+    }
+
+    private int parseSignature(String signature, int cur) {
+        char first;
+        do {
+            first = signature.charAt(cur++);
+        } while (first == '[');
+
+        switch (first) {
+            case 'L':
+                while (signature.charAt(cur) != ';') {
+                    cur++;
+                }
+                cur++;
+                break;
+            case 'V':
+            case 'I':
+            case 'B':
+            case 'C':
+            case 'D':
+            case 'F':
+            case 'J':
+            case 'S':
+            case 'Z':
+                break;
+            default:
+                assert false;
+        }
+        return cur;
+    }
+
+    @Override
+    public int argumentCount(boolean withReceiver) {
+        return arguments.size() + (withReceiver ? 1 : 0);
+    }
+
+    @Override
+    public CiKind argumentKindAt(int index) {
+        return CiKind.fromTypeString(arguments.get(index));
+    }
+
+    @Override
+    public int argumentSlots(boolean withReceiver) {
+
+        int argSlots = 0;
+        for (int i = 0; i < argumentCount(false); i++) {
+            argSlots += argumentKindAt(i).sizeInSlots();
+        }
+
+        return argSlots + (withReceiver ? 1 : 0);
+    }
+
+    @Override
+    public RiType argumentTypeAt(int index, RiType accessingClass) {
+        if (argumentTypes == null) {
+            argumentTypes = new RiType[arguments.size()];
+        }
+        RiType type = argumentTypes[index];
+        if (type == null) {
+            type = compiler.lookupType(arguments.get(index), (HotSpotTypeResolved) accessingClass);
+            argumentTypes[index] = type;
+        }
+        return type;
+    }
+
+    @Override
+    public String asString() {
+        return originalString;
+    }
+
+    @Override
+    public CiKind returnKind() {
+        return CiKind.fromTypeString(returnType);
+    }
+
+    @Override
+    public RiType returnType(RiType accessingClass) {
+        if (returnTypeCache == null) {
+            returnTypeCache = compiler.lookupType(returnType, (HotSpotTypeResolved) accessingClass);
+        }
+        return returnTypeCache;
+    }
+
+    @Override
+    public String toString() {
+        return "HotSpotSignature<" + originalString + ">";
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotTarget.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,41 @@
+/*
+ * 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.max.graal.runtime;
+
+import com.sun.cri.ci.*;
+
+/**
+ * HotSpot-specific CiTarget that provides the correct stack frame size alignment.
+ */
+public class HotSpotTarget extends CiTarget {
+
+    public HotSpotTarget(CiArchitecture arch, boolean isMP, int spillSlotSize, int stackAlignment, int pageSize, int cacheAlignment, boolean inlineObjects) {
+        super(arch, isMP, spillSlotSize, stackAlignment, pageSize, cacheAlignment, inlineObjects, true);
+    }
+
+    @Override
+    public int alignFrameSize(int frameSize) {
+        // account for the stored rbp value
+        return super.alignFrameSize(frameSize + wordSize) - wordSize;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotTargetMethod.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,106 @@
+/*
+ * 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.max.graal.runtime;
+
+import java.util.*;
+
+import com.oracle.max.graal.runtime.logging.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ci.CiTargetMethod.*;
+
+/**
+ * CiTargetMethod augmented with HotSpot-specific information.
+ */
+public final class HotSpotTargetMethod extends CompilerObject {
+
+    public final CiTargetMethod targetMethod;
+    public final HotSpotMethodResolved method; // used only for methods
+    public final String name; // used only for stubs
+
+    public final Site[] sites;
+    public final ExceptionHandler[] exceptionHandlers;
+
+    private HotSpotTargetMethod(Compiler compiler, HotSpotMethodResolved method, CiTargetMethod targetMethod) {
+        super(compiler);
+        this.method = method;
+        this.targetMethod = targetMethod;
+        this.name = null;
+
+        sites = getSortedSites(targetMethod);
+        if (targetMethod.exceptionHandlers == null) {
+            exceptionHandlers = null;
+        } else {
+            exceptionHandlers = targetMethod.exceptionHandlers.toArray(new ExceptionHandler[targetMethod.exceptionHandlers.size()]);
+        }
+    }
+
+    private HotSpotTargetMethod(Compiler compiler, CiTargetMethod targetMethod, String name) {
+        super(compiler);
+        this.method = null;
+        this.targetMethod = targetMethod;
+        this.name = name;
+
+        sites = getSortedSites(targetMethod);
+        assert targetMethod.exceptionHandlers == null || targetMethod.exceptionHandlers.size() == 0;
+        exceptionHandlers = null;
+    }
+
+    private Site[] getSortedSites(CiTargetMethod target) {
+        List<?>[] lists = new List<?>[] {target.directCalls, target.indirectCalls, target.safepoints, target.dataReferences, target.marks};
+        int count = 0;
+        for (List<?> list : lists) {
+            count += list.size();
+        }
+        Site[] result = new Site[count];
+        int pos = 0;
+        for (List<?> list : lists) {
+            for (Object elem : list) {
+                result[pos++] = (Site) elem;
+            }
+        }
+        Arrays.sort(result, new Comparator<Site>() {
+
+            public int compare(Site s1, Site s2) {
+                if (s1.pcOffset == s2.pcOffset && (s1 instanceof Mark ^ s2 instanceof Mark)) {
+                    return s1 instanceof Mark ? -1 : 1;
+                }
+                return s1.pcOffset - s2.pcOffset;
+            }
+        });
+        if (Logger.ENABLED) {
+            for (Site site : result) {
+                Logger.log(site.pcOffset + ": " + site);
+            }
+        }
+        return result;
+    }
+
+    public static void installMethod(Compiler compiler, HotSpotMethodResolved method, CiTargetMethod targetMethod) {
+        compiler.getVMEntries().installMethod(new HotSpotTargetMethod(compiler, method, targetMethod));
+    }
+
+    public static Object installStub(Compiler compiler, CiTargetMethod targetMethod, String name) {
+        return compiler.getVMEntries().installStub(new HotSpotTargetMethod(compiler, targetMethod, name));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotType.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,41 @@
+/*
+ * 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.max.graal.runtime;
+
+import com.sun.cri.ri.*;
+
+/**
+ * Common interface for all HotSpot RiType-implementations.
+ */
+public abstract class HotSpotType extends CompilerObject implements RiType {
+    protected String name;
+
+    protected HotSpotType(Compiler compiler) {
+        super(compiler);
+    }
+
+    @Override
+    public final String name() {
+        return name;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotTypePrimitive.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,162 @@
+/*
+ * 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.max.graal.runtime;
+
+import com.oracle.max.graal.compiler.util.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * Implementation of RiType for primitive HotSpot types.
+ */
+public final class HotSpotTypePrimitive extends HotSpotType {
+
+    private CiKind kind;
+
+
+    HotSpotTypePrimitive(Compiler compiler, CiKind kind) {
+        super(compiler);
+        this.kind = kind;
+        this.name = kind.toString();
+    }
+
+    @Override
+    public int accessFlags() {
+        return kind.toJavaClass().getModifiers();
+    }
+
+    @Override
+    public RiType arrayOf() {
+        return compiler.getVMEntries().getPrimitiveArrayType(kind);
+    }
+
+    @Override
+    public RiType componentType() {
+        return null;
+    }
+
+    @Override
+    public RiType exactType() {
+        return this;
+    }
+
+    @Override
+    public RiType superType() {
+        return null;
+    }
+
+    @Override
+    public CiConstant getEncoding(Representation r) {
+        throw Util.unimplemented("HotSpotTypePrimitive.getEncoding");
+    }
+
+    @Override
+    public CiKind getRepresentationKind(Representation r) {
+        return kind;
+    }
+
+    @Override
+    public boolean hasFinalizableSubclass() {
+        return false;
+    }
+
+    @Override
+    public boolean hasFinalizer() {
+        return false;
+    }
+
+    @Override
+    public boolean hasSubclass() {
+        return false;
+    }
+
+    @Override
+    public boolean isArrayClass() {
+        return false;
+    }
+
+    @Override
+    public boolean isInitialized() {
+        return true;
+    }
+
+    @Override
+    public boolean isInstance(CiConstant obj) {
+        return false;
+    }
+
+    @Override
+    public boolean isInstanceClass() {
+        return false;
+    }
+
+    @Override
+    public boolean isInterface() {
+        return false;
+    }
+
+    @Override
+    public boolean isResolved() {
+        return true;
+    }
+
+    @Override
+    public boolean isSubtypeOf(RiType other) {
+        return false;
+    }
+
+    @Override
+    public CiKind kind() {
+        return kind;
+    }
+
+    @Override
+    public RiMethod resolveMethodImpl(RiMethod method) {
+        return null;
+    }
+
+    @Override
+    public String toString() {
+        return "HotSpotTypePrimitive<" + kind + ">";
+    }
+
+    @Override
+    public RiType uniqueConcreteSubtype() {
+        return this;
+    }
+
+    @Override
+    public RiMethod uniqueConcreteMethod(RiMethod method) {
+        return null;
+    }
+
+    @Override
+    public RiField[] fields() {
+        return null;
+    }
+
+    @Override
+    public RiMethod getMethod(String name, String signature) {
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotTypeResolved.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,38 @@
+/*
+ * 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.max.graal.runtime;
+
+import com.oracle.max.graal.runtime.server.*;
+import com.sun.cri.ri.*;
+
+public interface HotSpotTypeResolved extends RiType, Remote {
+
+    String toString();
+
+    RiConstantPool constantPool();
+
+    int instanceSize();
+
+    RiField createRiField(String name, RiType type, int offset, int flags);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotTypeResolvedImpl.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,238 @@
+/*
+ * 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.max.graal.runtime;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * Implementation of RiType for resolved non-primitive HotSpot classes.
+ */
+public final class HotSpotTypeResolvedImpl extends HotSpotType implements HotSpotTypeResolved {
+
+    private Class javaMirror;
+    private String simpleName;
+    private int accessFlags;
+    private boolean hasFinalizer;
+    private boolean hasSubclass;
+    private boolean hasFinalizableSubclass;
+    private boolean isArrayClass;
+    private boolean isInstanceClass;
+    private boolean isInterface;
+    private int instanceSize;
+    private RiType componentType;
+    private HashMap<Long, RiField> fieldCache;
+    private RiConstantPool pool;
+    private RiType superType;
+    private boolean superTypeSet;
+    private RiField[] fields;
+
+    private HotSpotTypeResolvedImpl() {
+        super(null);
+    }
+
+    @Override
+    public int accessFlags() {
+        return accessFlags;
+    }
+
+    @Override
+    public RiType arrayOf() {
+        return compiler.getVMEntries().RiType_arrayOf(this);
+    }
+
+    @Override
+    public RiType componentType() {
+        return compiler.getVMEntries().RiType_componentType(this);
+    }
+
+    @Override
+    public RiType uniqueConcreteSubtype() {
+        return compiler.getVMEntries().RiType_uniqueConcreteSubtype(this);
+    }
+
+    @Override
+    public RiType superType() {
+        if (!superTypeSet) {
+            superType = compiler.getVMEntries().RiType_superType(this);
+            superTypeSet = true;
+        }
+        return superType;
+    }
+
+    @Override
+    public RiType exactType() {
+        if (Modifier.isFinal(accessFlags)) {
+            return this;
+        }
+        return null;
+    }
+
+    @Override
+    public CiConstant getEncoding(Representation r) {
+        switch (r) {
+            case JavaClass:
+                return CiConstant.forObject(javaMirror);
+            case ObjectHub:
+                return CiConstant.forObject(this);
+            case StaticFields:
+                return CiConstant.forObject(javaMirror);
+            case TypeInfo:
+                return CiConstant.forObject(this);
+            default:
+                return null;
+        }
+    }
+
+    @Override
+    public CiKind getRepresentationKind(Representation r) {
+        return CiKind.Object;
+    }
+
+    @Override
+    public boolean hasFinalizableSubclass() {
+        return hasFinalizableSubclass;
+    }
+
+    @Override
+    public boolean hasFinalizer() {
+        return hasFinalizer;
+    }
+
+    @Override
+    public boolean hasSubclass() {
+        return hasSubclass;
+    }
+
+    @Override
+    public boolean isArrayClass() {
+        return isArrayClass;
+    }
+
+    @Override
+    public boolean isInitialized() {
+        return compiler.getVMEntries().RiType_isInitialized(this);
+    }
+
+    @Override
+    public boolean isInstance(CiConstant obj) {
+        return javaMirror.isInstance(obj);
+    }
+
+    @Override
+    public boolean isInstanceClass() {
+        return isInstanceClass;
+    }
+
+    @Override
+    public boolean isInterface() {
+        return isInterface;
+    }
+
+    @Override
+    public boolean isResolved() {
+        return true;
+    }
+
+    @Override
+    public boolean isSubtypeOf(RiType other) {
+        if (other instanceof HotSpotTypeResolved) {
+            return compiler.getVMEntries().RiType_isSubtypeOf(this, other);
+        }
+        // No resolved type is a subtype of an unresolved type.
+        return false;
+    }
+
+    @Override
+    public CiKind kind() {
+        return CiKind.Object;
+    }
+
+    @Override
+    public RiMethod resolveMethodImpl(RiMethod method) {
+        assert method instanceof HotSpotMethod;
+        return compiler.getVMEntries().RiType_resolveMethodImpl(this, method.name(), method.signature().asString());
+    }
+
+    @Override
+    public String toString() {
+        return "HotSpotType<" + simpleName + ", resolved>";
+    }
+
+    @Override
+    public RiConstantPool constantPool() {
+        // TODO: Implement constant pool without the need for VmId and cache the constant pool.
+        return compiler.getVMEntries().RiType_constantPool(this);
+    }
+
+    @Override
+    public int instanceSize() {
+        return instanceSize;
+    }
+
+    @Override
+    public RiField createRiField(String name, RiType type, int offset, int flags) {
+        RiField result = null;
+
+        long id = offset + ((long) flags << 32);
+
+        // (tw) Must cache the fields, because the local load elimination only works if the objects from two field lookups are equal.
+        if (fieldCache == null) {
+            fieldCache = new HashMap<Long, RiField>(8);
+        } else {
+            result = fieldCache.get(id);
+        }
+
+        if (result == null) {
+            result = new HotSpotField(compiler, this, name, type, offset, flags);
+            fieldCache.put(id, result);
+        } else {
+            assert result.name().equals(name);
+            assert result.accessFlags() == flags;
+        }
+
+        return result;
+    }
+
+    @Override
+    public RiMethod uniqueConcreteMethod(RiMethod method) {
+        assert method instanceof HotSpotMethodResolved;
+        return ((HotSpotMethodResolved) method).uniqueConcreteMethod();
+    }
+
+    @Override
+    public RiField[] fields() {
+        if (fields == null) {
+            fields = compiler.getVMEntries().RiType_fields(this);
+        }
+        return fields;
+    }
+
+    @Override
+    public RiMethod getMethod(String name, String signature) {
+        return compiler.getVMEntries().RiType_resolveMethodImpl(this, name, signature);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotTypeUnresolved.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,213 @@
+/*
+ * 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.max.graal.runtime;
+
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * Implementation of RiType for unresolved HotSpot classes.
+ */
+public class HotSpotTypeUnresolved extends HotSpotType {
+
+    public final String simpleName;
+    public final int dimensions;
+
+    /**
+     * Creates a new unresolved type for a specified type descriptor.
+     */
+    public HotSpotTypeUnresolved(Compiler compiler, String name) {
+        super(compiler);
+        assert name.length() > 0 : "name cannot be empty";
+
+        int dimensions = 0;
+        // Decode name if necessary.
+        if (name.charAt(name.length() - 1) == ';') {
+            int startIndex = 0;
+            while (name.charAt(startIndex) == '[') {
+                startIndex++;
+                dimensions++;
+            }
+            assert name.charAt(startIndex) == 'L';
+            this.simpleName = name.substring(startIndex + 1, name.length() - 1);
+            this.name = name;
+        } else {
+            this.simpleName = name;
+            this.name = getFullName(name, dimensions);
+        }
+
+        this.dimensions = dimensions;
+    }
+
+    public HotSpotTypeUnresolved(Compiler compiler, String name, int dimensions) {
+        super(compiler);
+        assert dimensions >= 0;
+        this.simpleName = name;
+        this.dimensions = dimensions;
+        this.name = getFullName(name, dimensions);
+    }
+
+    private String getFullName(String name, int dimensions) {
+        StringBuilder str = new StringBuilder();
+        for (int i = 0; i < dimensions; i++) {
+            str.append('[');
+        }
+        str.append('L').append(simpleName).append(';');
+        return str.toString();
+    }
+
+    @Override
+    public RiType uniqueConcreteSubtype() {
+        throw unresolved("uniqueConcreteSubtype");
+    }
+
+    @Override
+    public boolean hasSubclass() {
+        throw unresolved("hasSubclass()");
+    }
+
+    @Override
+    public boolean hasFinalizer() {
+        throw unresolved("hasFinalizer()");
+    }
+
+    @Override
+    public boolean hasFinalizableSubclass() {
+        throw unresolved("hasFinalizableSubclass()");
+    }
+
+    @Override
+    public boolean isInterface() {
+        throw unresolved("isInterface()");
+    }
+
+    @Override
+    public boolean isArrayClass() {
+        return dimensions > 0;
+    }
+
+    @Override
+    public boolean isInstanceClass() {
+        throw unresolved("isInstanceClass()");
+    }
+
+    @Override
+    public int accessFlags() {
+        throw unresolved("accessFlags()");
+    }
+
+    @Override
+    public boolean isResolved() {
+        return false;
+    }
+
+    @Override
+    public boolean isInitialized() {
+        throw unresolved("isInitialized()");
+    }
+
+    @Override
+    public boolean isSubtypeOf(RiType other) {
+        throw unresolved("isSubtypeOf()");
+    }
+
+    @Override
+    public boolean isInstance(CiConstant obj) {
+        throw unresolved("isInstance()");
+    }
+
+    @Override
+    public RiType componentType() {
+        assert isArrayClass() : "no array class" + name();
+        return new HotSpotTypeUnresolved(compiler, simpleName, dimensions - 1);
+    }
+
+    @Override
+    public RiType exactType() {
+        throw unresolved("exactType()");
+    }
+
+    @Override
+    public RiType superType() {
+        throw unresolved("superType()");
+    }
+
+    @Override
+    public RiType arrayOf() {
+        return new HotSpotTypeUnresolved(compiler, simpleName, dimensions + 1);
+    }
+
+    @Override
+    public RiMethod resolveMethodImpl(RiMethod method) {
+        throw unresolved("resolveMethodImpl()");
+    }
+
+    @Override
+    public CiKind kind() {
+        return CiKind.Object;
+    }
+
+    private CiUnresolvedException unresolved(String operation) {
+        throw new CiUnresolvedException(operation + " not defined for unresolved class " + simpleName);
+    }
+
+    @Override
+    public int hashCode() {
+        return simpleName.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        return o == this;
+    }
+
+    @Override
+    public String toString() {
+        return "HotSpotType<" + simpleName + ", unresolved>";
+    }
+
+    @Override
+    public CiConstant getEncoding(RiType.Representation r) {
+        throw unresolved("getEncoding()");
+    }
+
+    @Override
+    public CiKind getRepresentationKind(RiType.Representation r) {
+        return CiKind.Object;
+    }
+
+    @Override
+    public RiMethod uniqueConcreteMethod(RiMethod method) {
+        throw unresolved("uniqueConcreteMethod");
+    }
+
+    @Override
+    public RiField[] fields() {
+        return null;
+    }
+
+    @Override
+    public RiMethod getMethod(String name, String signature) {
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotVMConfig.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,119 @@
+/*
+ * 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.max.graal.runtime;
+
+import com.sun.cri.ci.*;
+
+/**
+ * Used to communicate configuration details, runtime offsets, etc. to graal upon compileMethod.
+ */
+public final class HotSpotVMConfig extends CompilerObject {
+
+    private HotSpotVMConfig() {
+        super(null);
+    }
+
+    // os information, register layout, code generation, ...
+    public boolean windowsOs;
+    public int codeEntryAlignment;
+    public boolean verifyPointers;
+    public boolean useFastLocking;
+    public boolean useFastNewObjectArray;
+    public boolean useFastNewTypeArray;
+
+    // offsets, ...
+    public int vmPageSize;
+    public int stackShadowPages;
+    public int hubOffset;
+    public int arrayLengthOffset;
+    public int klassStateOffset;
+    public int klassStateFullyInitialized;
+    public int[] arrayOffsets;
+    public int arrayClassElementOffset;
+    public int threadTlabTopOffset;
+    public int threadTlabEndOffset;
+    public int threadObjectOffset;
+    public int instanceHeaderPrototypeOffset;
+    public int threadExceptionOopOffset;
+    public int threadExceptionPcOffset;
+    public int threadMultiNewArrayStorage;
+    public long cardtableStartAddress;
+    public int cardtableShift;
+    public long safepointPollingAddress;
+    public int classMirrorOffset;
+
+    // runtime stubs
+    public long debugStub;
+    public long instanceofStub;
+    public long newInstanceStub;
+    public long unresolvedNewInstanceStub;
+    public long newTypeArrayStub;
+    public long newObjectArrayStub;
+    public long newMultiArrayStub;
+    public long loadKlassStub;
+    public long accessFieldStub;
+    public long resolveStaticCallStub;
+    public long inlineCacheMissStub;
+    public long unwindExceptionStub;
+    public long handleExceptionStub;
+    public long handleDeoptStub;
+    public long monitorEnterStub;
+    public long monitorExitStub;
+    public long fastMonitorEnterStub;
+    public long fastMonitorExitStub;
+    public long verifyPointerStub;
+
+    public void check() {
+        assert vmPageSize >= 16;
+        assert codeEntryAlignment > 0;
+        assert stackShadowPages > 0;
+    }
+
+    public int getArrayOffset(CiKind kind) {
+        return arrayOffsets[getKindNumber(kind)];
+    }
+
+    private int getKindNumber(CiKind kind) {
+        if (kind == CiKind.Boolean) {
+            return 0;
+        } else if (kind == CiKind.Byte) {
+            return 1;
+        } else if (kind == CiKind.Short) {
+            return 2;
+        } else if (kind == CiKind.Char) {
+            return 3;
+        } else if (kind == CiKind.Int) {
+            return 4;
+        } else if (kind == CiKind.Float) {
+            return 5;
+        } else if (kind == CiKind.Long) {
+            return 6;
+        } else if (kind == CiKind.Double) {
+            return 7;
+        } else if (kind == CiKind.Object) {
+            return 8;
+        } else {
+            throw new RuntimeException(kind + " is not a Java kind");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotXirGenerator.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,1372 @@
+/*
+ * 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.max.graal.runtime;
+
+import static com.oracle.max.graal.runtime.TemplateFlag.*;
+import static com.sun.cri.ci.CiCallingConvention.Type.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+import com.oracle.max.asm.target.amd64.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ci.CiAddress.*;
+import com.sun.cri.ci.CiRegister.*;
+import com.sun.cri.ri.*;
+import com.sun.cri.ri.RiType.*;
+import com.sun.cri.xir.*;
+import com.sun.cri.xir.CiXirAssembler.XirLabel;
+import com.sun.cri.xir.CiXirAssembler.*;
+
+public class HotSpotXirGenerator implements RiXirGenerator {
+
+    // this needs to correspond to graal_CodeInstaller.hpp
+    // @formatter:off
+    private static final Integer MARK_VERIFIED_ENTRY            = 0x0001;
+    private static final Integer MARK_UNVERIFIED_ENTRY          = 0x0002;
+    private static final Integer MARK_OSR_ENTRY                 = 0x0003;
+    private static final Integer MARK_UNWIND_ENTRY              = 0x0004;
+    private static final Integer MARK_EXCEPTION_HANDLER_ENTRY   = 0x0005;
+    private static final Integer MARK_DEOPT_HANDLER_ENTRY       = 0x0006;
+
+    private static final Integer MARK_STATIC_CALL_STUB          = 0x1000;
+
+    private static final Integer MARK_INVOKE_INVALID            = 0x2000;
+    private static final Integer MARK_INVOKEINTERFACE           = 0x2001;
+    private static final Integer MARK_INVOKESTATIC              = 0x2002;
+    private static final Integer MARK_INVOKESPECIAL             = 0x2003;
+    private static final Integer MARK_INVOKEVIRTUAL             = 0x2004;
+
+    private static final Integer MARK_IMPLICIT_NULL             = 0x3000;
+
+    private static final Integer MARK_KLASS_PATCHING            = 0x4000;
+    private static final Integer MARK_DUMMY_OOP_RELOCATION      = 0x4001;
+    private static final Integer MARK_ACCESS_FIELD_PATCHING     = 0x4002;
+    // @formatter:on
+
+    private final HotSpotVMConfig config;
+    private final CiTarget target;
+    private final RiRegisterConfig registerConfig;
+    private final Compiler compiler;
+
+    private CiXirAssembler globalAsm;
+
+    public HotSpotXirGenerator(HotSpotVMConfig config, CiTarget target, RiRegisterConfig registerConfig, Compiler compiler) {
+        this.config = config;
+        this.target = target;
+        this.registerConfig = registerConfig;
+        this.compiler = compiler;
+    }
+
+    private SimpleTemplates prologueTemplates = new SimpleTemplates(STATIC_METHOD) {
+
+        @Override
+        protected XirTemplate create(CiXirAssembler asm, long flags) {
+            asm.restart(CiKind.Void);
+            XirOperand framePointer = asm.createRegisterTemp("frame pointer", CiKind.Word, AMD64.rbp);
+            XirOperand stackPointer = asm.createRegisterTemp("stack pointer", CiKind.Word, AMD64.rsp);
+            XirLabel unverifiedStub = null;
+
+            asm.mark(MARK_OSR_ENTRY);
+            asm.mark(MARK_UNVERIFIED_ENTRY);
+            if (!is(STATIC_METHOD, flags)) {
+                unverifiedStub = asm.createOutOfLineLabel("unverified");
+
+                XirOperand temp = asm.createRegisterTemp("temp (r10)", CiKind.Word, AMD64.r10);
+                XirOperand cache = asm.createRegisterTemp("cache (rax)", CiKind.Word, AMD64.rax);
+
+                CiCallingConvention conventions = registerConfig.getCallingConvention(JavaCallee, new CiKind[] {CiKind.Object}, target, false);
+                XirOperand receiver = asm.createRegisterTemp("receiver", CiKind.Word, conventions.locations[0].asRegister());
+
+                asm.pload(CiKind.Word, temp, receiver, asm.i(config.hubOffset), false);
+                asm.jneq(unverifiedStub, cache, temp);
+            }
+            asm.align(config.codeEntryAlignment);
+            asm.mark(MARK_VERIFIED_ENTRY);
+            asm.stackOverflowCheck();
+            asm.push(framePointer);
+            asm.mov(framePointer, stackPointer);
+            asm.pushFrame();
+
+            // -- out of line -------------------------------------------------------
+            XirOperand thread = asm.createRegisterTemp("thread", CiKind.Word, AMD64.r15);
+            XirOperand exceptionOop = asm.createTemp("exception oop", CiKind.Object);
+            XirLabel unwind = asm.createOutOfLineLabel("unwind");
+            asm.bindOutOfLine(unwind);
+
+            asm.mark(MARK_UNWIND_ENTRY);
+
+            asm.pload(CiKind.Object, exceptionOop, thread, asm.i(config.threadExceptionOopOffset), false);
+            asm.pstore(CiKind.Object, thread, asm.i(config.threadExceptionOopOffset), asm.createConstant(CiConstant.NULL_OBJECT), false);
+            asm.pstore(CiKind.Long, thread, asm.i(config.threadExceptionPcOffset), asm.l(0), false);
+
+            asm.callRuntime(config.unwindExceptionStub, null, exceptionOop);
+            asm.shouldNotReachHere();
+
+            asm.mark(MARK_EXCEPTION_HANDLER_ENTRY);
+            asm.callRuntime(config.handleExceptionStub, null);
+            asm.shouldNotReachHere();
+
+            asm.nop(1);
+            asm.mark(MARK_DEOPT_HANDLER_ENTRY);
+            asm.callRuntime(config.handleDeoptStub, null);
+            asm.shouldNotReachHere();
+
+            if (!is(STATIC_METHOD, flags)) {
+                asm.bindOutOfLine(unverifiedStub);
+                asm.jmpRuntime(config.inlineCacheMissStub);
+            }
+
+            return asm.finishTemplate(is(STATIC_METHOD, flags) ? "static prologue" : "prologue");
+        }
+    };
+
+    private SimpleTemplates epilogueTemplates = new SimpleTemplates(STATIC_METHOD, SYNCHRONIZED) {
+
+        @Override
+        protected XirTemplate create(CiXirAssembler asm, long flags) {
+            asm.restart(CiKind.Void);
+            XirOperand framePointer = asm.createRegisterTemp("frame pointer", CiKind.Word, AMD64.rbp);
+
+            asm.popFrame();
+            asm.pop(framePointer);
+
+            // TODO safepoint check
+
+            return asm.finishTemplate("epilogue");
+        }
+    };
+
+    private SimpleTemplates safepointTemplates = new SimpleTemplates() {
+
+        @Override
+        protected XirTemplate create(CiXirAssembler asm, long flags) {
+            asm.restart(CiKind.Void);
+
+            XirOperand temp = asm.createRegister("temp", CiKind.Word, AMD64.rax);
+            asm.pload(CiKind.Word, temp, asm.w(config.safepointPollingAddress), true);
+
+            return asm.finishTemplate("safepoint");
+        }
+    };
+
+    private SimpleTemplates exceptionObjectTemplates = new SimpleTemplates() {
+
+        @Override
+        protected XirTemplate create(CiXirAssembler asm, long flags) {
+            XirOperand result = asm.restart(CiKind.Object);
+            XirOperand thread = asm.createRegisterTemp("thread", CiKind.Word, AMD64.r15);
+
+            asm.pload(CiKind.Object, result, thread, asm.i(config.threadExceptionOopOffset), false);
+            asm.pstore(CiKind.Object, thread, asm.i(config.threadExceptionOopOffset), asm.o(null), false);
+            asm.pstore(CiKind.Long, thread, asm.i(config.threadExceptionPcOffset), asm.l(0), false);
+
+            return asm.finishTemplate("exception object");
+        }
+    };
+
+    private SimpleTemplates invokeInterfaceTemplates = new SimpleTemplates(NULL_CHECK) {
+
+        @Override
+        protected XirTemplate create(CiXirAssembler asm, long flags) {
+            asm.restart();
+            XirParameter receiver = asm.createInputParameter("receiver", CiKind.Object);
+            XirParameter addr = asm.createConstantInputParameter("addr", CiKind.Word);
+            XirOperand temp = asm.createRegisterTemp("temp", CiKind.Word, AMD64.rax);
+
+            if (is(NULL_CHECK, flags)) {
+                asm.nop(1);
+                asm.mark(MARK_IMPLICIT_NULL);
+                asm.pload(CiKind.Word, temp, receiver, true);
+            }
+            asm.mark(MARK_INVOKEINTERFACE);
+            asm.mov(temp, asm.createConstant(CiConstant.forObject(HotSpotProxy.DUMMY_CONSTANT_OBJ)));
+
+            return asm.finishTemplate(addr, "invokeinterface");
+        }
+    };
+
+    private SimpleTemplates invokeVirtualTemplates = new SimpleTemplates(NULL_CHECK) {
+
+        @Override
+        protected XirTemplate create(CiXirAssembler asm, long flags) {
+            asm.restart();
+            XirParameter receiver = asm.createInputParameter("receiver", CiKind.Object);
+            XirParameter addr = asm.createConstantInputParameter("addr", CiKind.Word);
+            XirOperand temp = asm.createRegisterTemp("temp", CiKind.Word, AMD64.rax);
+
+            if (is(NULL_CHECK, flags)) {
+                asm.nop(1);
+                asm.mark(MARK_IMPLICIT_NULL);
+                asm.pload(CiKind.Word, temp, receiver, true);
+            }
+            asm.mark(MARK_INVOKEVIRTUAL);
+            asm.mov(temp, asm.createConstant(CiConstant.forObject(HotSpotProxy.DUMMY_CONSTANT_OBJ)));
+
+            return asm.finishTemplate(addr, "invokevirtual");
+        }
+    };
+
+    private SimpleTemplates invokeSpecialTemplates = new SimpleTemplates(NULL_CHECK) {
+
+        @Override
+        protected XirTemplate create(CiXirAssembler asm, long flags) {
+            asm.restart();
+            XirParameter receiver = asm.createInputParameter("receiver", CiKind.Object);
+            XirParameter addr = asm.createConstantInputParameter("addr", CiKind.Word);
+            XirOperand temp = asm.createRegisterTemp("temp", CiKind.Word, AMD64.rax);
+            XirLabel stub = asm.createOutOfLineLabel("call stub");
+
+            if (is(NULL_CHECK, flags)) {
+                asm.nop(1);
+                asm.mark(MARK_IMPLICIT_NULL);
+                asm.pload(CiKind.Word, temp, receiver, true);
+            }
+            asm.mark(MARK_INVOKESPECIAL);
+
+            // -- out of line -------------------------------------------------------
+            asm.bindOutOfLine(stub);
+            XirOperand method = asm.createRegisterTemp("method", CiKind.Word, AMD64.rbx);
+            asm.mark(MARK_STATIC_CALL_STUB, XirMark.CALLSITE);
+            asm.mov(method, asm.w(0L));
+            XirLabel dummy = asm.createOutOfLineLabel("dummy");
+            asm.jmp(dummy);
+            asm.bindOutOfLine(dummy);
+
+            return asm.finishTemplate(addr, "invokespecial");
+        }
+    };
+
+    private SimpleTemplates invokeStaticTemplates = new SimpleTemplates() {
+
+        @Override
+        protected XirTemplate create(CiXirAssembler asm, long flags) {
+            asm.restart();
+            XirParameter addr = asm.createConstantInputParameter("addr", CiKind.Word);
+
+            XirLabel stub = asm.createOutOfLineLabel("call stub");
+            asm.mark(MARK_INVOKESTATIC);
+
+            // -- out of line -------------------------------------------------------
+            asm.bindOutOfLine(stub);
+            XirOperand method = asm.createRegisterTemp("method", CiKind.Word, AMD64.rbx);
+            asm.mark(MARK_STATIC_CALL_STUB, XirMark.CALLSITE);
+            asm.mov(method, asm.w(0L));
+            XirLabel dummy = asm.createOutOfLineLabel("dummy");
+            asm.jmp(dummy);
+            asm.bindOutOfLine(dummy);
+
+            return asm.finishTemplate(addr, "invokestatic");
+        }
+    };
+
+    private SimpleTemplates monitorEnterTemplates = new SimpleTemplates(NULL_CHECK) {
+
+        @Override
+        protected XirTemplate create(CiXirAssembler asm, long flags) {
+            asm.restart(CiKind.Void);
+            XirParameter object = asm.createInputParameter("object", CiKind.Object);
+            XirParameter lock = asm.createInputParameter("lock", CiKind.Word);
+
+            if (is(NULL_CHECK, flags)) {
+                asm.nop(1);
+                asm.mark(MARK_IMPLICIT_NULL);
+                asm.pload(CiKind.Word, asm.createTemp("temp", CiKind.Word), object, true);
+            }
+
+
+            // (tw) It is important to use for this runtime call the debug info AFTER the monitor enter. Otherwise the monitor object
+            // is not correctly garbage collected.
+            final boolean useInfoAfter = true;
+
+            if (config.useFastLocking) {
+                useRegisters(asm, AMD64.rax, AMD64.rbx);
+                useRegisters(asm, getGeneralParameterRegister(0));
+                useRegisters(asm, getGeneralParameterRegister(1));
+                asm.callRuntime(config.fastMonitorEnterStub, null, useInfoAfter, object, lock);
+            } else {
+                asm.reserveOutgoingStack(target.wordSize * 2);
+                asm.pstore(CiKind.Object, asm.createRegister("rsp", CiKind.Word, AMD64.RSP.asRegister()), asm.i(target.wordSize), object, false);
+                asm.pstore(CiKind.Word, asm.createRegister("rsp", CiKind.Word, AMD64.RSP.asRegister()), asm.i(0), lock, false);
+                asm.callRuntime(config.monitorEnterStub, null, useInfoAfter);
+            }
+
+            return asm.finishTemplate("monitorEnter");
+        }
+    };
+
+    private CiRegister getGeneralParameterRegister(int index) {
+        return registerConfig.getCallingConventionRegisters(CiCallingConvention.Type.RuntimeCall, RegisterFlag.CPU)[index];
+    }
+
+    private SimpleTemplates monitorExitTemplates = new SimpleTemplates(NULL_CHECK) {
+
+        @Override
+        protected XirTemplate create(CiXirAssembler asm, long flags) {
+            asm.restart(CiKind.Void);
+            XirParameter object = asm.createInputParameter("object", CiKind.Object);
+            XirParameter lock = asm.createInputParameter("lock", CiKind.Word);
+
+            if (config.useFastLocking) {
+                useRegisters(asm, AMD64.rax, AMD64.rbx);
+                useRegisters(asm, getGeneralParameterRegister(0));
+                useRegisters(asm, getGeneralParameterRegister(1));
+                asm.callRuntime(config.fastMonitorExitStub, null, object, lock);
+            } else {
+                asm.reserveOutgoingStack(target.wordSize);
+                asm.pstore(CiKind.Word, asm.createRegister("rsp", CiKind.Word, AMD64.RSP.asRegister()), asm.i(0), lock, false);
+                asm.callRuntime(config.monitorExitStub, null);
+            }
+
+            return asm.finishTemplate("monitorExit");
+        }
+    };
+
+    private KindTemplates getFieldTemplates = new KindTemplates(NULL_CHECK) {
+
+        @Override
+        protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) {
+            XirOperand result = asm.restart(kind);
+            XirParameter object = asm.createInputParameter("object", CiKind.Object);
+
+            XirParameter fieldOffset = asm.createConstantInputParameter("fieldOffset", CiKind.Int);
+            if (is(NULL_CHECK, flags)) {
+                asm.nop(1);
+                asm.mark(MARK_IMPLICIT_NULL);
+            }
+            asm.pload(kind, result, object, fieldOffset, is(NULL_CHECK, flags));
+            return asm.finishTemplate("getfield<" + kind + ">");
+        }
+    };
+
+    private KindTemplates writeBarrierTemplate = new KindTemplates() {
+
+        @Override
+        protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) {
+            asm.restart(CiKind.Void);
+            XirParameter object = asm.createInputParameter("object", CiKind.Object);
+
+            // Need temp operand, because the write barrier destroys the object pointer.
+            XirOperand temp = asm.createTemp("temp", CiKind.Object);
+            asm.mov(temp, object);
+
+            writeBarrier(asm, temp);
+            return asm.finishTemplate("writeBarrier");
+        }
+    };
+
+    private KindTemplates putFieldTemplates = new KindTemplates(WRITE_BARRIER, NULL_CHECK) {
+
+        @Override
+        protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) {
+            asm.restart(CiKind.Void);
+            XirParameter object = asm.createInputParameter("object", CiKind.Object);
+            XirParameter value = asm.createInputParameter("value", kind);
+            XirParameter fieldOffset = asm.createConstantInputParameter("fieldOffset", CiKind.Int);
+            if (kind == CiKind.Object) {
+                verifyPointer(asm, value);
+            }
+            if (is(NULL_CHECK, flags)) {
+                asm.nop(1);
+                asm.mark(MARK_IMPLICIT_NULL);
+            }
+            asm.pstore(kind, object, fieldOffset, value, is(NULL_CHECK, flags));
+            if (is(WRITE_BARRIER, flags) && kind == CiKind.Object) {
+                XirOperand temp = asm.createTemp("temp", CiKind.Word);
+                asm.mov(temp, object);
+                writeBarrier(asm, temp);
+            }
+            return asm.finishTemplate("putfield<" + kind + ">");
+        }
+    };
+
+    private final IndexTemplates newInstanceTemplates = new IndexTemplates() {
+
+        @Override
+        protected XirTemplate create(CiXirAssembler asm, long flags, int size) {
+            XirOperand result = asm.restart(CiKind.Word);
+            XirOperand type = asm.createInputParameter("type", CiKind.Object);
+
+            XirOperand temp1 = asm.createRegisterTemp("temp1", CiKind.Word, AMD64.rcx);
+            XirOperand temp2 = asm.createRegisterTemp("temp2", CiKind.Word, AMD64.rbx);
+            XirOperand temp2i = asm.createRegisterTemp("temp2i", CiKind.Int, AMD64.rbx);
+            useRegisters(asm, AMD64.rsi);
+            XirLabel tlabFull = asm.createOutOfLineLabel("tlab full");
+            XirLabel resume = asm.createInlineLabel("resume");
+
+            // check if the class is already initialized
+            asm.pload(CiKind.Int, temp2i, type, asm.i(config.klassStateOffset), false);
+            asm.jneq(tlabFull, temp2i, asm.i(config.klassStateFullyInitialized));
+
+            XirOperand thread = asm.createRegisterTemp("thread", CiKind.Word, AMD64.r15);
+            asm.pload(CiKind.Word, result, thread, asm.i(config.threadTlabTopOffset), false);
+            asm.add(temp1, result, asm.w(size));
+            asm.pload(CiKind.Word, temp2, thread, asm.i(config.threadTlabEndOffset), false);
+
+            asm.jgt(tlabFull, temp1, temp2);
+            asm.pstore(CiKind.Word, thread, asm.i(config.threadTlabTopOffset), temp1, false);
+
+            asm.bindInline(resume);
+
+            asm.pload(CiKind.Word, temp1, type, asm.i(config.instanceHeaderPrototypeOffset), false);
+            asm.pstore(CiKind.Word, result, temp1, false);
+            asm.pstore(CiKind.Object, result, asm.i(config.hubOffset), type, false);
+
+            if (size > 2 * target.wordSize) {
+                asm.mov(temp1, asm.w(0));
+                for (int offset = 2 * target.wordSize; offset < size; offset += target.wordSize) {
+                    asm.pstore(CiKind.Word, result, asm.i(offset), temp1, false);
+                }
+            }
+
+            // -- out of line -------------------------------------------------------
+            asm.bindOutOfLine(tlabFull);
+            XirOperand arg = asm.createRegisterTemp("runtime call argument", CiKind.Object, AMD64.rdx);
+            asm.mov(arg, type);
+            useRegisters(asm, AMD64.rax);
+            asm.callRuntime(config.newInstanceStub, result);
+            asm.jmp(resume);
+
+            return asm.finishTemplate("new instance");
+        }
+    };
+
+    private SimpleTemplates newObjectArrayCloneTemplates = new SimpleTemplates() {
+
+        @Override
+        protected XirTemplate create(CiXirAssembler asm, long flags) {
+            XirOperand result = asm.restart(CiKind.Object);
+            XirParameter lengthParam = asm.createInputParameter("length", CiKind.Int, true);
+            XirParameter src = asm.createInputParameter("src", CiKind.Object);
+
+            // Set up length and hub.
+            XirOperand length = asm.createRegisterTemp("length", CiKind.Int, AMD64.rbx);
+            XirOperand hub = asm.createRegisterTemp("hub", CiKind.Object, AMD64.rdx);
+            asm.pload(CiKind.Object, hub, src, asm.i(config.hubOffset), false);
+            asm.mov(length, lengthParam);
+
+            useRegisters(asm, AMD64.rsi, AMD64.rcx, AMD64.rdi, AMD64.rax);
+            asm.callRuntime(config.newObjectArrayStub, result);
+            return asm.finishTemplate("objectArrayClone");
+        }
+    };
+
+    private SimpleTemplates newObjectArrayTemplates = new SimpleTemplates() {
+
+        @Override
+        protected XirTemplate create(CiXirAssembler asm, long flags) {
+            emitNewTypeArray(asm, flags, CiKind.Object, config.useFastNewObjectArray, config.newObjectArrayStub);
+            return asm.finishTemplate("newObjectArray");
+        }
+    };
+
+    private void emitNewTypeArray(CiXirAssembler asm, long flags, CiKind kind, boolean useFast, long slowPathStub) {
+        XirOperand result = asm.restart(CiKind.Word);
+
+        XirParameter lengthParam = asm.createInputParameter("length", CiKind.Int, true);
+
+        XirOperand length = asm.createRegisterTemp("length", CiKind.Int, AMD64.rbx);
+        XirOperand hub = asm.createRegisterTemp("hub", CiKind.Object, AMD64.rdx);
+
+        // Registers rsi, rcx, rdi, and rax are needed by the runtime call.
+        // Hub needs to be on rdx, length on rbx.
+        XirOperand temp1 = asm.createRegisterTemp("temp1", CiKind.Word, AMD64.rcx);
+        XirOperand temp2 = asm.createRegisterTemp("temp2", CiKind.Word, AMD64.rax);
+        XirOperand temp3 = asm.createRegisterTemp("temp3", CiKind.Word, AMD64.rdi);
+        XirOperand size = asm.createRegisterTemp("size", CiKind.Int, AMD64.rsi);
+
+        asm.mov(hub, asm.createConstantInputParameter("hub", CiKind.Object));
+        asm.mov(length, lengthParam);
+
+        if (useFast) {
+
+            XirLabel slowPath = asm.createOutOfLineLabel("slowPath");
+
+            XirLabel done = asm.createInlineLabel("done");
+
+            // Check for negative array size.
+            // TODO: Also check for upper bound
+            asm.jlt(slowPath, length, asm.i(0));
+
+            final int aligning = target.wordSize;
+            final int arrayLengthOffset = target.wordSize * 2;
+            final int arrayElementOffset = config.getArrayOffset(kind);
+
+            // Calculate aligned size
+            asm.mov(size, length);
+            int scale = CiUtil.log2(kind.sizeInBytes(target.wordSize));
+            if (scale != 0) {
+                asm.shl(size, size, asm.i(scale));
+            }
+            asm.add(size, size, asm.i(arrayElementOffset + aligning - 1));
+            long mask = 0xFFFFFFFFL;
+            mask <<= CiUtil.log2(aligning);
+            asm.and(size, size, asm.i((int) mask));
+
+            // Try tlab allocation
+            XirOperand thread = asm.createRegisterTemp("thread", CiKind.Word, AMD64.r15);
+            asm.pload(CiKind.Word, result, thread, asm.i(config.threadTlabTopOffset), false);
+            asm.add(temp1, result, size);
+            asm.pload(CiKind.Word, temp2, thread, asm.i(config.threadTlabEndOffset), false);
+            asm.jgt(slowPath, temp1, temp2);
+            asm.pstore(CiKind.Word, thread, asm.i(config.threadTlabTopOffset), temp1, false);
+
+            // Now the new object is in result, store mark word and klass
+            asm.pload(CiKind.Word, temp1, hub, asm.i(config.instanceHeaderPrototypeOffset), false);
+            asm.pstore(CiKind.Word, result, temp1, false);
+            asm.pstore(CiKind.Object, result, asm.i(config.hubOffset), hub, false);
+
+            // Store array length
+            asm.pstore(CiKind.Int, result, asm.i(arrayLengthOffset), length, false);
+
+            // Initialize with 0
+            XirLabel top = asm.createInlineLabel("top");
+            asm.sub(size, size, asm.i(arrayElementOffset));
+            asm.shr(size, size, asm.i(Scale.Times8.log2));
+            asm.jeq(done, size, asm.i(0));
+            asm.xor(temp3, temp3, temp3);
+            asm.bindInline(top);
+            asm.pstore(CiKind.Word, result, size, temp3, arrayElementOffset - target.wordSize, Scale.Times8, false);
+            asm.decAndJumpNotZero(top, size);
+
+            asm.bindInline(done);
+
+            // Slow path
+            asm.bindOutOfLine(slowPath);
+            asm.callRuntime(slowPathStub, result);
+            asm.jmp(done);
+        } else {
+            asm.callRuntime(slowPathStub, result);
+        }
+    }
+
+    private KindTemplates newTypeArrayTemplates = new KindTemplates() {
+        @Override
+        protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) {
+            emitNewTypeArray(asm, flags, kind, config.useFastNewTypeArray, config.newTypeArrayStub);
+            return asm.finishTemplate("newTypeArray<" + kind.toString() + ">");
+        }
+    };
+
+    private final IndexTemplates multiNewArrayTemplate = new IndexTemplates() {
+
+        @Override
+        protected XirTemplate create(CiXirAssembler asm, long flags, int dimensions) {
+            XirOperand result = asm.restart(CiKind.Object);
+
+            XirOperand hub = asm.createRegisterTemp("hub", CiKind.Object, AMD64.rax);
+            XirOperand rank = asm.createRegisterTemp("rank", CiKind.Int, AMD64.rbx);
+            XirOperand sizes = asm.createRegisterTemp("sizes", CiKind.Long, AMD64.rcx);
+            XirOperand thread = asm.createRegisterTemp("thread", CiKind.Long, AMD64.r15);
+            asm.add(sizes, thread, asm.l(config.threadMultiNewArrayStorage));
+            for (int i = 0; i < dimensions; i++) {
+                XirParameter length = asm.createInputParameter("length" + i, CiKind.Int, true);
+                asm.pstore(CiKind.Int, sizes, asm.i(i * target.sizeInBytes(CiKind.Int)), length, false);
+            }
+
+            asm.mov(hub, asm.createConstantInputParameter("hub", CiKind.Object));
+
+            asm.mov(rank, asm.i(dimensions));
+            useRegisters(asm, AMD64.rax);
+            asm.callRuntime(config.newMultiArrayStub, result);
+            return asm.finishTemplate("multiNewArray" + dimensions);
+        }
+    };
+
+    private SimpleTemplates checkCastTemplates = new SimpleTemplates(NULL_CHECK) {
+
+        @Override
+        protected XirTemplate create(CiXirAssembler asm, long flags) {
+            asm.restart();
+            XirParameter object = asm.createInputParameter("object", CiKind.Object);
+            final XirOperand hub;
+            hub = asm.createConstantInputParameter("hub", CiKind.Object);
+
+            XirOperand objHub = asm.createTemp("objHub", CiKind.Object);
+
+            XirLabel end = asm.createInlineLabel("end");
+            XirLabel slowPath = asm.createOutOfLineLabel("slow path");
+
+            if (is(NULL_CHECK, flags)) {
+                // null can be cast to anything
+                asm.jeq(end, object, asm.o(null));
+            }
+
+            asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false);
+            // if we get an exact match: succeed immediately
+            asm.jneq(slowPath, objHub, hub);
+            asm.bindInline(end);
+
+            // -- out of line -------------------------------------------------------
+            asm.bindOutOfLine(slowPath);
+            checkSubtype(asm, objHub, objHub, hub);
+            asm.jneq(end, objHub, asm.o(null));
+            XirOperand scratch = asm.createRegisterTemp("scratch", CiKind.Word, AMD64.r10);
+            asm.mov(scratch, asm.createConstant(CiConstant.forWord(0)));
+
+            asm.callRuntime(CiRuntimeCall.Deoptimize, null);
+            asm.shouldNotReachHere();
+
+            return asm.finishTemplate(object, "checkcast");
+        }
+    };
+
+    private SimpleTemplates instanceOfTemplates = new SimpleTemplates(NULL_CHECK) {
+
+        @Override
+        protected XirTemplate create(CiXirAssembler asm, long flags) {
+            asm.restart(CiKind.Void);
+            XirParameter object = asm.createInputParameter("object", CiKind.Object);
+            final XirOperand hub;
+            hub = asm.createConstantInputParameter("hub", CiKind.Object);
+
+            XirOperand objHub = asm.createTemp("objHub", CiKind.Object);
+
+            XirLabel slowPath = asm.createOutOfLineLabel("slow path");
+            XirLabel trueSucc = asm.createInlineLabel(XirLabel.TrueSuccessor);
+            XirLabel falseSucc = asm.createInlineLabel(XirLabel.FalseSuccessor);
+
+            if (is(NULL_CHECK, flags)) {
+                // null isn't "instanceof" anything
+                asm.jeq(falseSucc, object, asm.o(null));
+            }
+
+            asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false);
+            // if we get an exact match: succeed immediately
+            asm.jeq(trueSucc, objHub, hub);
+            asm.jmp(slowPath);
+
+            // -- out of line -------------------------------------------------------
+            asm.bindOutOfLine(slowPath);
+            checkSubtype(asm, objHub, objHub, hub);
+            asm.jeq(falseSucc, objHub, asm.o(null));
+            asm.jmp(trueSucc);
+
+            return asm.finishTemplate("instanceof");
+        }
+    };
+
+    private XirOperand genArrayLength(CiXirAssembler asm, XirOperand array, boolean implicitNullException) {
+        XirOperand length = asm.createTemp("length", CiKind.Int);
+        genArrayLength(asm, length, array, implicitNullException);
+        return length;
+    }
+
+    private void genArrayLength(CiXirAssembler asm, XirOperand length, XirOperand array, boolean implicitNullException) {
+        if (implicitNullException) {
+            asm.nop(1);
+            asm.mark(MARK_IMPLICIT_NULL);
+        }
+        asm.pload(CiKind.Int, length, array, asm.i(config.arrayLengthOffset), implicitNullException);
+    }
+
+    private KindTemplates arrayLoadTemplates = new KindTemplates(NULL_CHECK, READ_BARRIER, BOUNDS_CHECK, GIVEN_LENGTH) {
+
+        @Override
+        protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) {
+            XirOperand result = asm.restart(kind);
+            XirParameter array = asm.createInputParameter("array", CiKind.Object);
+            XirParameter index = asm.createInputParameter("index", CiKind.Int, true);
+            XirLabel failBoundsCheck = null;
+            // if the length is known the array cannot be null
+            boolean implicitNullException = is(NULL_CHECK, flags);
+
+            if (is(BOUNDS_CHECK, flags)) {
+                // load the array length and check the index
+                failBoundsCheck = asm.createOutOfLineLabel("failBoundsCheck");
+                XirOperand length;
+                if (is(GIVEN_LENGTH, flags)) {
+                    length = asm.createInputParameter("length", CiKind.Int, true);
+                } else {
+                    length = genArrayLength(asm, array, implicitNullException);
+                }
+                asm.jugteq(failBoundsCheck, index, length);
+                implicitNullException = false;
+            }
+            int elemSize = target.sizeInBytes(kind);
+            if (implicitNullException) {
+                asm.nop(1);
+                asm.mark(MARK_IMPLICIT_NULL);
+            }
+            asm.pload(kind, result, array, index, config.getArrayOffset(kind), Scale.fromInt(elemSize), implicitNullException);
+            if (is(BOUNDS_CHECK, flags)) {
+                asm.bindOutOfLine(failBoundsCheck);
+                XirOperand scratch = asm.createRegisterTemp("scratch", CiKind.Word, AMD64.r10);
+                asm.mov(scratch, asm.createConstant(CiConstant.forWord(0)));
+                asm.callRuntime(CiRuntimeCall.Deoptimize, null);
+                asm.shouldNotReachHere();
+            }
+            return asm.finishTemplate("arrayload<" + kind + ">");
+        }
+    };
+
+    private SimpleTemplates getClassTemplates = new SimpleTemplates() {
+       @Override
+       protected XirTemplate create(CiXirAssembler asm, long flags) {
+           XirOperand result = asm.restart(CiKind.Object);
+           XirOperand object = asm.createInputParameter("object", CiKind.Object);
+           if (is(NULL_CHECK, flags)) {
+               asm.nop(1);
+           }
+           asm.pload(CiKind.Object, result, object, asm.i(config.hubOffset), is(NULL_CHECK, flags));
+           asm.pload(CiKind.Object, result, result, asm.i(config.classMirrorOffset), false);
+           return asm.finishTemplate("getClass");
+       }
+    };
+
+    private SimpleTemplates currentThreadTemplates = new SimpleTemplates() {
+       @Override
+       protected XirTemplate create(CiXirAssembler asm, long flags) {
+           XirOperand result = asm.restart(CiKind.Object);
+           XirOperand thread = asm.createRegisterTemp("thread", CiKind.Word, AMD64.r15);
+           asm.pload(CiKind.Object, result, thread, asm.i(config.threadObjectOffset), false);
+           return asm.finishTemplate("currentThread");
+       }
+    };
+
+    @Override
+    public XirSnippet genCurrentThread(XirSite site) {
+        return new XirSnippet(currentThreadTemplates.get(site));
+    }
+
+    @Override
+    public XirSnippet genGetClass(XirSite site, XirArgument object) {
+        return new XirSnippet(getClassTemplates.get(site), object);
+    }
+
+    private KindTemplates arrayCopyTemplates = new KindTemplates() {
+
+        @Override
+        protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) {
+            asm.restart(CiKind.Void);
+            XirParameter src = asm.createInputParameter("src", CiKind.Object);
+            XirParameter srcPos = asm.createInputParameter("srcPos", CiKind.Int, true);
+            XirParameter dest = asm.createInputParameter("dest", CiKind.Object);
+            XirParameter destPos = asm.createInputParameter("destPos", CiKind.Int, true);
+            XirParameter length = asm.createInputParameter("length", CiKind.Int, true);
+
+            XirOperand tempSrc = asm.createTemp("tempSrc", CiKind.Word);
+            XirOperand tempDest = asm.createTemp("tempDest", CiKind.Word);
+            XirOperand lengthOperand = asm.createRegisterTemp("lengthOperand", CiKind.Int, AMD64.rax);
+
+            XirOperand compHub = null;
+            XirOperand valueHub = null;
+            XirOperand temp = null;
+            XirLabel store = null;
+            XirLabel slowStoreCheck = null;
+
+            if (is(STORE_CHECK, flags) && kind == CiKind.Object) {
+                valueHub = asm.createRegisterTemp("valueHub", CiKind.Word, AMD64.rdi);
+                compHub = asm.createRegisterTemp("compHub", CiKind.Word, AMD64.rsi);
+                temp = asm.createRegisterTemp("temp", CiKind.Word, AMD64.r10);
+            }
+
+            // Calculate the factor for the repeat move instruction.
+            int elementSize = kind.sizeInBytes(target.wordSize);
+            int factor;
+            boolean wordSize;
+            if (elementSize >= target.wordSize) {
+                assert elementSize % target.wordSize == 0;
+                wordSize = true;
+                factor = elementSize / target.wordSize;
+            } else {
+                factor = elementSize;
+                wordSize = false;
+            }
+
+            // Adjust the length if the factor is not 1.
+            if (factor != 1) {
+                asm.shl(lengthOperand, length, asm.i(CiUtil.log2(factor)));
+            } else {
+                asm.mov(lengthOperand, length);
+            }
+
+            // Set the start and the end pointer.
+            asm.lea(tempSrc, src, srcPos, config.getArrayOffset(kind), Scale.fromInt(elementSize));
+            asm.lea(tempDest, dest, destPos, config.getArrayOffset(kind), Scale.fromInt(elementSize));
+
+            XirLabel reverse = null;
+            XirLabel normal = null;
+
+            if (is(STORE_CHECK, flags)) {
+                reverse = asm.createInlineLabel("reverse");
+                asm.jneq(reverse, src, dest);
+            }
+
+            if (!is(STORE_CHECK, flags) && !is(INPUTS_DIFFERENT, flags) && !is(INPUTS_SAME, flags)) {
+                normal = asm.createInlineLabel("normal");
+                asm.jneq(normal, src, dest);
+            }
+
+            if (!is(INPUTS_DIFFERENT, flags)) {
+                if (reverse == null) {
+                    reverse = asm.createInlineLabel("reverse");
+                }
+                asm.jlt(reverse, srcPos, destPos);
+            }
+
+            if (!is(STORE_CHECK, flags) && !is(INPUTS_DIFFERENT, flags) && !is(INPUTS_SAME, flags)) {
+                asm.bindInline(normal);
+            }
+
+            // Everything set up => repeat mov.
+            if (wordSize) {
+                asm.repmov(tempSrc, tempDest, lengthOperand);
+            } else {
+                asm.repmovb(tempSrc, tempDest, lengthOperand);
+            }
+
+            if (!is(INPUTS_DIFFERENT, flags) || is(STORE_CHECK, flags)) {
+
+                XirLabel end = asm.createInlineLabel("end");
+                asm.jmp(end);
+
+                // Implement reverse copy, because srcPos < destPos and src == dest.
+                asm.bindInline(reverse);
+
+                if (is(STORE_CHECK, flags)) {
+                    asm.pload(CiKind.Object, compHub, dest, asm.i(config.hubOffset), false);
+                    asm.pload(CiKind.Object, compHub, compHub, asm.i(config.arrayClassElementOffset), false);
+                }
+
+                CiKind copyKind = wordSize ? CiKind.Object : CiKind.Byte;
+                XirOperand tempValue = asm.createTemp("tempValue", copyKind);
+                XirLabel start = asm.createInlineLabel("start");
+                asm.bindInline(start);
+                asm.sub(lengthOperand, lengthOperand, asm.i(1));
+                asm.jlt(end, lengthOperand, asm.i(0));
+
+                Scale scale = wordSize ? Scale.fromInt(target.wordSize) : Scale.Times1;
+                asm.pload(copyKind, tempValue, tempSrc, lengthOperand, 0, scale, false);
+
+                if (is(STORE_CHECK, flags)) {
+                    slowStoreCheck = asm.createOutOfLineLabel("slowStoreCheck");
+                    store = asm.createInlineLabel("store");
+                    asm.jeq(store, tempValue, asm.o(null)); // first check if value is null
+                    asm.pload(CiKind.Object, valueHub, tempValue, asm.i(config.hubOffset), false);
+                    asm.jneq(slowStoreCheck, compHub, valueHub); // then check component hub matches value hub
+                    asm.bindInline(store);
+                }
+
+                asm.pstore(copyKind, tempDest, lengthOperand, tempValue, 0, scale, false);
+
+                asm.jmp(start);
+                asm.bindInline(end);
+            }
+
+            if (kind == CiKind.Object) {
+                // Do write barriers
+                asm.lea(tempDest, dest, destPos, config.getArrayOffset(kind), Scale.fromInt(elementSize));
+                asm.shr(tempDest, tempDest, asm.i(config.cardtableShift));
+                asm.pstore(CiKind.Boolean, asm.w(config.cardtableStartAddress), tempDest, asm.b(false), false);
+
+                XirOperand tempDestEnd = tempSrc; // Reuse src temp
+                asm.lea(tempDestEnd, dest, destPos, config.getArrayOffset(kind), Scale.fromInt(elementSize));
+                asm.add(tempDestEnd, tempDestEnd, length);
+                asm.shr(tempDestEnd, tempDestEnd, asm.i(config.cardtableShift));
+
+                // Jump to out-of-line write barrier loop if the array is big.
+                XirLabel writeBarrierLoop = asm.createOutOfLineLabel("writeBarrierLoop");
+                asm.jneq(writeBarrierLoop, tempDest, tempSrc);
+                XirLabel back = asm.createInlineLabel("back");
+                asm.bindInline(back);
+
+                asm.bindOutOfLine(writeBarrierLoop);
+                asm.pstore(CiKind.Boolean, asm.w(config.cardtableStartAddress), tempDestEnd, asm.b(false), false);
+                asm.sub(tempDestEnd, tempDestEnd, asm.i(1));
+                asm.jneq(writeBarrierLoop, tempDestEnd, tempDest);
+                asm.jmp(back);
+            }
+
+            if (is(STORE_CHECK, flags)) {
+                assert kind == CiKind.Object;
+                useRegisters(asm, AMD64.rax);
+                asm.bindOutOfLine(slowStoreCheck);
+                checkSubtype(asm, temp, valueHub, compHub);
+                asm.jneq(store, temp, asm.w(0));
+                XirOperand scratch = asm.createRegisterTemp("scratch", CiKind.Word, AMD64.r10);
+                asm.mov(scratch, asm.createConstant(CiConstant.forWord(0)));
+                asm.callRuntime(CiRuntimeCall.Deoptimize, null);
+                asm.jmp(store);
+            }
+
+            return asm.finishTemplate("arraycopy<" + kind + ">");
+        }
+    };
+
+    private KindTemplates arrayStoreTemplates = new KindTemplates(NULL_CHECK, WRITE_BARRIER, BOUNDS_CHECK, STORE_CHECK, GIVEN_LENGTH) {
+
+        @Override
+        protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) {
+            asm.restart(CiKind.Void);
+            XirParameter array = asm.createInputParameter("array", CiKind.Object);
+            XirParameter index = asm.createInputParameter("index", CiKind.Int, true);
+            XirParameter value = asm.createInputParameter("value", kind, kind != CiKind.Object);
+            XirOperand temp = asm.createTemp("temp", CiKind.Word);
+            XirOperand valueHub = null;
+            XirOperand compHub = null;
+            XirLabel store = asm.createInlineLabel("store");
+            XirLabel failBoundsCheck = null;
+            XirLabel slowStoreCheck = null;
+            // if the length is known the array cannot be null
+            boolean implicitNullException = is(NULL_CHECK, flags);
+
+            if (is(BOUNDS_CHECK, flags)) {
+                // load the array length and check the index
+                failBoundsCheck = asm.createOutOfLineLabel("failBoundsCheck");
+                XirOperand length;
+                if (is(GIVEN_LENGTH, flags)) {
+                    length = asm.createInputParameter("length", CiKind.Int);
+                } else {
+                    length = asm.createTemp("length", CiKind.Int);
+                    if (implicitNullException) {
+                        asm.nop(1);
+                        asm.mark(MARK_IMPLICIT_NULL);
+                    }
+                    asm.pload(CiKind.Int, length, array, asm.i(config.arrayLengthOffset), implicitNullException);
+                    implicitNullException = false;
+                }
+                asm.jugteq(failBoundsCheck, index, length);
+
+            }
+            if (is(STORE_CHECK, flags) && kind == CiKind.Object) {
+                slowStoreCheck = asm.createOutOfLineLabel("slowStoreCheck");
+                asm.jeq(store, value, asm.o(null)); // first check if value is null
+                valueHub = asm.createTemp("valueHub", CiKind.Object);
+                compHub = asm.createTemp("compHub", CiKind.Object);
+                if (implicitNullException) {
+                    asm.nop(1);
+                    asm.mark(MARK_IMPLICIT_NULL);
+                }
+                asm.pload(CiKind.Object, compHub, array, asm.i(config.hubOffset), implicitNullException);
+                asm.pload(CiKind.Object, compHub, compHub, asm.i(config.arrayClassElementOffset), false);
+                asm.pload(CiKind.Object, valueHub, value, asm.i(config.hubOffset), false);
+                asm.jneq(slowStoreCheck, compHub, valueHub); // then check component hub matches value hub
+
+                implicitNullException = false;
+            }
+            asm.bindInline(store);
+            int elemSize = target.sizeInBytes(kind);
+
+            if (implicitNullException) {
+                asm.nop(1);
+                asm.mark(MARK_IMPLICIT_NULL);
+            }
+            int disp = config.getArrayOffset(kind);
+            Scale scale = Scale.fromInt(elemSize);
+            if (kind == CiKind.Object) {
+                verifyPointer(asm, value);
+            }
+            if (is(WRITE_BARRIER, flags) && kind == CiKind.Object) {
+                asm.lea(temp, array, index, disp, scale);
+                asm.pstore(kind, temp, value, implicitNullException);
+                writeBarrier(asm, temp);
+            } else {
+                asm.pstore(kind, array, index, value, disp, scale, implicitNullException);
+            }
+
+            // -- out of line -------------------------------------------------------
+            if (is(BOUNDS_CHECK, flags)) {
+                asm.bindOutOfLine(failBoundsCheck);
+                XirOperand scratch = asm.createRegisterTemp("scratch", CiKind.Word, AMD64.r10);
+                asm.mov(scratch, asm.createConstant(CiConstant.forWord(0)));
+                asm.callRuntime(CiRuntimeCall.Deoptimize, null);
+                asm.shouldNotReachHere();
+            }
+            if (is(STORE_CHECK, flags) && kind == CiKind.Object) {
+                useRegisters(asm, AMD64.rax);
+                asm.bindOutOfLine(slowStoreCheck);
+                checkSubtype(asm, temp, valueHub, compHub);
+                asm.jneq(store, temp, asm.w(0));
+                XirOperand scratch = asm.createRegisterTemp("scratch", CiKind.Word, AMD64.r10);
+                asm.mov(scratch, asm.createConstant(CiConstant.forWord(0)));
+                asm.callRuntime(CiRuntimeCall.Deoptimize, null);
+                asm.shouldNotReachHere();
+            }
+            return asm.finishTemplate("arraystore<" + kind + ">");
+        }
+    };
+
+    private SimpleTemplates arrayLengthTemplates = new SimpleTemplates(NULL_CHECK) {
+
+        @Override
+        protected XirTemplate create(CiXirAssembler asm, long flags) {
+            XirOperand result = asm.restart(CiKind.Int);
+            XirParameter object = asm.createInputParameter("object", CiKind.Object);
+            if (is(NULL_CHECK, flags)) {
+                asm.nop(1);
+                asm.mark(MARK_IMPLICIT_NULL);
+            }
+            verifyPointer(asm, object);
+            asm.pload(CiKind.Int, result, object, asm.i(config.arrayLengthOffset), true);
+            return asm.finishTemplate("arrayLength");
+        }
+    };
+
+    private SimpleTemplates typeCheckTemplates = new SimpleTemplates(NULL_CHECK) {
+       @Override
+       protected XirTemplate create(CiXirAssembler asm, long flags) {
+           asm.restart();
+           XirParameter object = asm.createInputParameter("object", CiKind.Object);
+           XirOperand hub = asm.createConstantInputParameter("hub", CiKind.Object);
+
+           XirOperand objHub = asm.createTemp("objHub", CiKind.Object);
+
+           XirLabel slowPath = asm.createOutOfLineLabel("deopt");
+
+           if (is(NULL_CHECK, flags)) {
+               asm.nop(1);
+               asm.mark(MARK_IMPLICIT_NULL);
+           }
+
+           asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false);
+           // if we get an exact match: continue
+           asm.jneq(slowPath, objHub, hub);
+
+           // -- out of line -------------------------------------------------------
+           asm.bindOutOfLine(slowPath);
+           XirOperand scratch = asm.createRegisterTemp("scratch", CiKind.Word, AMD64.r10);
+           asm.mov(scratch, asm.createConstant(CiConstant.forWord(2)));
+
+           asm.callRuntime(CiRuntimeCall.Deoptimize, null);
+           asm.shouldNotReachHere();
+
+           return asm.finishTemplate(object, "typeCheck");
+       }
+    };
+
+    @Override
+    public XirSnippet genPrologue(XirSite site, RiMethod method) {
+        boolean staticMethod = Modifier.isStatic(method.accessFlags());
+        return new XirSnippet(staticMethod ? prologueTemplates.get(site, STATIC_METHOD) : prologueTemplates.get(site));
+    }
+
+    @Override
+    public XirSnippet genEpilogue(XirSite site, RiMethod method) {
+        return new XirSnippet(epilogueTemplates.get(site));
+    }
+
+    @Override
+    public XirSnippet genSafepoint(XirSite site) {
+        return new XirSnippet(safepointTemplates.get(site));
+    }
+
+    @Override
+    public XirSnippet genExceptionObject(XirSite site) {
+        return new XirSnippet(exceptionObjectTemplates.get(site));
+    }
+
+    @Override
+    public XirSnippet genResolveClass(XirSite site, RiType type, Representation rep) {
+        throw new CiBailout("Xir ResolveClass not available");
+    }
+
+    @Override
+    public XirSnippet genIntrinsic(XirSite site, XirArgument[] arguments, RiMethod method) {
+        return null;
+    }
+
+    @Override
+    public XirSnippet genInvokeInterface(XirSite site, XirArgument receiver, RiMethod method) {
+        return new XirSnippet(invokeInterfaceTemplates.get(site), receiver, XirArgument.forWord(0));
+    }
+
+    @Override
+    public XirSnippet genInvokeVirtual(XirSite site, XirArgument receiver, RiMethod method) {
+        return new XirSnippet(invokeVirtualTemplates.get(site), receiver, XirArgument.forWord(0));
+    }
+
+    @Override
+    public XirSnippet genInvokeSpecial(XirSite site, XirArgument receiver, RiMethod method) {
+        return new XirSnippet(invokeSpecialTemplates.get(site), receiver, XirArgument.forWord(0));
+    }
+
+    @Override
+    public XirSnippet genInvokeStatic(XirSite site, RiMethod method) {
+        return new XirSnippet(invokeStaticTemplates.get(site), XirArgument.forWord(0));
+    }
+
+    @Override
+    public XirSnippet genMonitorEnter(XirSite site, XirArgument receiver, XirArgument lockAddress) {
+        return new XirSnippet(monitorEnterTemplates.get(site), receiver, lockAddress);
+    }
+
+    @Override
+    public XirSnippet genMonitorExit(XirSite site, XirArgument receiver, XirArgument lockAddress) {
+        return new XirSnippet(monitorExitTemplates.get(site), receiver, lockAddress);
+    }
+
+    @Override
+    public XirSnippet genGetField(XirSite site, XirArgument object, RiField field) {
+        assert field.isResolved();
+        return new XirSnippet(getFieldTemplates.get(site, field.kind()), object, XirArgument.forInt(((HotSpotField) field).offset()));
+    }
+
+    @Override
+    public XirSnippet genWriteBarrier(XirArgument object) {
+        return new XirSnippet(writeBarrierTemplate.get(null, CiKind.Void), object);
+    }
+
+    @Override
+    public XirSnippet genPutField(XirSite site, XirArgument object, RiField field, XirArgument value) {
+        assert field.isResolved();
+        return new XirSnippet(putFieldTemplates.get(site, field.kind()), object, value, XirArgument.forInt(((HotSpotField) field).offset()));
+    }
+
+    @Override
+    public XirSnippet genGetStatic(XirSite site, XirArgument object, RiField field) {
+        assert field.isResolved();
+        return new XirSnippet(getFieldTemplates.get(site, field.kind()), object, XirArgument.forInt(((HotSpotField) field).offset()));
+    }
+
+    @Override
+    public XirSnippet genPutStatic(XirSite site, XirArgument object, RiField field, XirArgument value) {
+        assert field.isResolved();
+        return new XirSnippet(putFieldTemplates.get(site, field.kind()), object, value, XirArgument.forInt(((HotSpotField) field).offset()));
+    }
+
+    @Override
+    public XirSnippet genNewInstance(XirSite site, RiType type) {
+        assert type.isResolved();
+        int instanceSize = ((HotSpotTypeResolved) type).instanceSize();
+        return new XirSnippet(newInstanceTemplates.get(site, instanceSize), XirArgument.forObject(type));
+    }
+
+    @Override
+    public XirSnippet genNewArray(XirSite site, XirArgument length, CiKind elementKind, RiType componentType, RiType arrayType) {
+        if (elementKind == CiKind.Object) {
+            assert arrayType.isResolved();
+            return new XirSnippet(newObjectArrayTemplates.get(site), length, XirArgument.forObject(arrayType));
+        }
+        assert arrayType == null;
+        arrayType = compiler.getVMEntries().getPrimitiveArrayType(elementKind);
+        return new XirSnippet(newTypeArrayTemplates.get(site, elementKind), length, XirArgument.forObject(arrayType));
+    }
+
+    @Override
+    public XirSnippet genNewObjectArrayClone(XirSite site, XirArgument newLength, XirArgument referenceArray) {
+        return new XirSnippet(newObjectArrayCloneTemplates.get(site), newLength, referenceArray);
+    }
+
+    @Override
+    public XirSnippet genNewMultiArray(XirSite site, XirArgument[] lengths, RiType type) {
+        assert type.isResolved();
+        XirArgument[] params = Arrays.copyOf(lengths, lengths.length + 1);
+        params[lengths.length] = XirArgument.forObject(type);
+        return new XirSnippet(multiNewArrayTemplate.get(site, lengths.length), params);
+    }
+
+    @Override
+    public XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type) {
+        return new XirSnippet(checkCastTemplates.get(site), receiver, hub);
+    }
+
+    @Override
+    public XirSnippet genInstanceOf(XirSite site, XirArgument object, XirArgument hub, RiType type) {
+        assert type.isResolved();
+        return new XirSnippet(instanceOfTemplates.get(site), object, hub);
+    }
+
+    @Override
+    public XirSnippet genArrayLoad(XirSite site, XirArgument array, XirArgument index, XirArgument length, CiKind elementKind, RiType elementType) {
+        if (length == null || !site.requiresBoundsCheck()) {
+            return new XirSnippet(arrayLoadTemplates.get(site, elementKind), array, index);
+        }
+        return new XirSnippet(arrayLoadTemplates.get(site, elementKind, GIVEN_LENGTH), array, index, length);
+    }
+
+    @Override
+    public XirSnippet genArrayStore(XirSite site, XirArgument array, XirArgument index, XirArgument length, XirArgument value, CiKind elementKind, RiType elementType) {
+        if (length == null || !site.requiresBoundsCheck()) {
+            return new XirSnippet(arrayStoreTemplates.get(site, elementKind), array, index, value);
+        }
+        return new XirSnippet(arrayStoreTemplates.get(site, elementKind, GIVEN_LENGTH), array, index, value, length);
+    }
+
+    @Override
+    public XirSnippet genArrayCopy(XirSite site, XirArgument src, XirArgument srcPos, XirArgument dest, XirArgument destPos, XirArgument length, RiType elementType, boolean inputsSame, boolean inputsDifferent) {
+        if (elementType == null) {
+            return null;
+        }
+        assert !inputsDifferent || !inputsSame;
+        XirTemplate template = null;
+        if (inputsDifferent) {
+            template = arrayCopyTemplates.get(site, elementType.kind(), INPUTS_DIFFERENT);
+        } else if (inputsSame) {
+            template = arrayCopyTemplates.get(site, elementType.kind(), INPUTS_SAME);
+        } else {
+            template = arrayCopyTemplates.get(site, elementType.kind());
+        }
+        return new XirSnippet(template, src, srcPos, dest, destPos, length);
+    }
+
+    @Override
+    public XirSnippet genArrayLength(XirSite site, XirArgument array) {
+        return new XirSnippet(arrayLengthTemplates.get(site), array);
+    }
+
+    @Override
+    public XirSnippet genTypeCheck(XirSite site, XirArgument object, XirArgument hub, RiType type) {
+        assert type.isResolved();
+        return new XirSnippet(typeCheckTemplates.get(site), object, hub);
+    }
+
+    @Override
+    public List<XirTemplate> buildTemplates(CiXirAssembler asm) {
+        this.globalAsm = asm;
+        List<XirTemplate> templates = new ArrayList<XirTemplate>();
+        return templates;
+    }
+
+    private void verifyPointer(CiXirAssembler asm, XirOperand pointer) {
+        if (config.verifyPointers) {
+            // The verify pointer stub wants the argument in a fixed register.
+            XirOperand fixed = asm.createRegisterTemp("fixed", CiKind.Object, AMD64.r13);
+            asm.push(fixed);
+            asm.mov(fixed, pointer);
+            asm.callRuntime(config.verifyPointerStub, null);
+            asm.pop(fixed);
+        }
+    }
+
+    private void checkSubtype(CiXirAssembler asm, XirOperand result, XirOperand objHub, XirOperand hub) {
+        asm.push(objHub);
+        asm.push(hub);
+        asm.callRuntime(config.instanceofStub, null);
+        asm.pop(result);
+        asm.pop(result);
+    }
+
+    private void useRegisters(CiXirAssembler asm, CiRegister... registers) {
+        if (registers != null) {
+            for (CiRegister register : registers) {
+                asm.createRegisterTemp("reg", CiKind.Illegal, register);
+            }
+        }
+    }
+
+    private void writeBarrier(CiXirAssembler asm, XirOperand base) {
+        asm.shr(base, base, asm.i(config.cardtableShift));
+        asm.pstore(CiKind.Boolean, asm.w(config.cardtableStartAddress), base, asm.b(false), false);
+    }
+
+    public boolean is(TemplateFlag check, long flags) {
+        return (flags & check.bits()) == check.bits();
+    }
+
+    /**
+     * Base class for all the ondemand template generators. It is not normally subclassed directly, but through one of
+     * its subclasses (SimpleTemplates, KindTemplates, IndexTemplates).
+     *
+     * @author Lukas Stadler
+     */
+    private abstract class Templates {
+
+        private ConcurrentHashMap<Long, XirTemplate> templates = new ConcurrentHashMap<Long, XirTemplate>();
+        private final long mask;
+
+        /**
+         * Each flag passed to this method will cause templates with and without it to be generated.
+         */
+        public Templates(TemplateFlag... flags) {
+            this.mask = getBits((int) INDEX_MASK, null, flags);
+        }
+
+        protected abstract XirTemplate create(CiXirAssembler asm, long flags);
+
+        protected long getBits(int index, XirSite site, TemplateFlag... flags) {
+            long bits = index;
+            if (site != null) {
+                bits |= site.requiresNullCheck() ? NULL_CHECK.bits() : 0;
+                bits |= site.requiresReadBarrier() ? READ_BARRIER.bits() : 0;
+                bits |= site.requiresWriteBarrier() ? WRITE_BARRIER.bits() : 0;
+                bits |= site.requiresArrayStoreCheck() ? STORE_CHECK.bits() : 0;
+                bits |= site.requiresBoundsCheck() ? BOUNDS_CHECK.bits() : 0;
+            }
+            if (flags != null) {
+                for (TemplateFlag flag : flags) {
+                    bits |= flag.bits();
+                }
+            }
+            return bits;
+        }
+
+        protected XirTemplate getInternal(long flags) {
+            flags = flags & mask;
+            XirTemplate template = templates.get(flags);
+            if (template == null) {
+                template = create(HotSpotXirGenerator.this.globalAsm.copy(), flags);
+                templates.put(flags, template);
+            }
+            return template;
+        }
+    }
+
+    private abstract class SimpleTemplates extends Templates {
+
+        public SimpleTemplates(TemplateFlag... flags) {
+            super(flags);
+        }
+
+        public XirTemplate get(XirSite site, TemplateFlag... flags) {
+            return getInternal(getBits(0, site, flags));
+        }
+    }
+
+    private abstract class IndexTemplates extends Templates {
+
+        public IndexTemplates(TemplateFlag... flags) {
+            super(flags);
+        }
+
+        @Override
+        protected final XirTemplate create(CiXirAssembler asm, long flags) {
+            return create(asm, flags & FLAGS_MASK, (int) (flags & INDEX_MASK));
+        }
+
+        protected abstract XirTemplate create(CiXirAssembler asm, long flags, int index);
+
+        public XirTemplate get(XirSite site, int size, TemplateFlag... flags) {
+            return getInternal(getBits(size, site, flags));
+        }
+    }
+
+    private abstract class KindTemplates extends Templates {
+
+        public KindTemplates(TemplateFlag... flags) {
+            super(flags);
+        }
+
+        @Override
+        protected final XirTemplate create(CiXirAssembler asm, long flags) {
+            return create(asm, flags & FLAGS_MASK, CiKind.VALUES[(int) (flags & INDEX_MASK)]);
+        }
+
+        protected abstract XirTemplate create(CiXirAssembler asm, long flags, CiKind kind);
+
+        public XirTemplate get(XirSite site, CiKind kind, TemplateFlag... flags) {
+            return getInternal(getBits(kind.ordinal(), site, flags));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/InvocationSocket.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,276 @@
+/*
+ * 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.max.graal.runtime;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.oracle.max.graal.runtime.logging.*;
+
+/**
+ * A collection of java.lang.reflect proxies that communicate over a socket connection.
+ *
+ * Calling a method sends the method name and the parameters through the socket. Afterwards this class waits for a
+ * result. While waiting for a result three types of objects can arrive through the socket: a method invocation, a
+ * method result or an exception. Method invocation can thus be recursive.
+ */
+public class InvocationSocket {
+
+    private static final boolean DEBUG = false;
+    private static final boolean COUNT_CALLS = false;
+
+    private static final HashSet<String> cachedMethodNames = new HashSet<String>();
+    private static final HashSet<String> forbiddenMethodNames = new HashSet<String>();
+
+    static {
+        cachedMethodNames.add("name");
+        cachedMethodNames.add("kind");
+        cachedMethodNames.add("isResolved");
+        cachedMethodNames.add("getVMEntries");
+        cachedMethodNames.add("exactType");
+        cachedMethodNames.add("isInitialized");
+        forbiddenMethodNames.add("javaClass");
+    }
+
+    private final ObjectOutputStream output;
+    private final ObjectInputStream input;
+
+    private final Map<String, Integer> counts = new HashMap<String, Integer>();
+
+    public InvocationSocket(ObjectOutputStream output, ObjectInputStream input) {
+        this.output = output;
+        this.input = input;
+
+        if (COUNT_CALLS) {
+            Runtime.getRuntime().addShutdownHook(new Thread() {
+                @Override
+                public void run() {
+                    SortedMap<Integer, String> sorted = new TreeMap<Integer, String>();
+                    for (Map.Entry<String, Integer> entry : counts.entrySet()) {
+                        sorted.put(entry.getValue(), entry.getKey());
+                    }
+                    for (Map.Entry<Integer, String> entry : sorted.entrySet()) {
+                        System.out.println(entry.getKey() + ": " + entry.getValue());
+                    }
+                }
+            });
+        }
+    }
+
+    /**
+     * Represents one invocation of a method that is transferred via the socket connection.
+     *
+     * @author Lukas Stadler
+     */
+    private static class Invocation implements Serializable {
+
+        public Object receiver;
+        public String methodName;
+        public Object[] args;
+
+        public Invocation(Object receiver, String methodName, Object[] args) {
+            this.receiver = receiver;
+            this.methodName = methodName;
+            this.args = args;
+        }
+    }
+
+    /**
+     * Represents the result of an invocation that is transferred via the socket connection.
+     *
+     * @author Lukas Stadler
+     */
+    private static class Result implements Serializable {
+
+        public Object result;
+
+        public Result(Object result) {
+            this.result = result;
+        }
+    }
+
+    private void incCount(String name, Object[] args) {
+        if (COUNT_CALLS) {
+            name = name + (args == null ? 0 : args.length);
+            if (counts.get(name) != null) {
+                counts.put(name, counts.get(name) + 1);
+            } else {
+                counts.put(name, 1);
+            }
+        }
+    }
+
+    /**
+     * Each instance of this class handles remote invocations for one instance of a Remote class. It will forward all
+     * interface methods to the other end of the socket and cache the results of calls to certain methods.
+     *
+     * @author Lukas Stadler
+     */
+    public class Handler implements InvocationHandler {
+
+        private final Object receiver;
+        private final HashMap<String, Object> cache = new HashMap<String, Object>();
+
+        public Handler(Object receiver) {
+            this.receiver = receiver;
+        }
+
+        @Override
+        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+            // only interface methods can be transferred, java.lang.Object methods
+            if (method.getDeclaringClass() == Object.class) {
+                return method.invoke(receiver, args);
+            }
+            String methodName = method.getName();
+            // check if the result of this zero-arg method was cached
+            if (args == null || args.length == 0) {
+                if (cache.containsKey(methodName)) {
+                    return cache.get(methodName);
+                }
+            }
+            if (forbiddenMethodNames.contains(methodName)) {
+                throw new IllegalAccessException(methodName + " not allowed");
+            }
+            Object result = null;
+            try {
+                if (DEBUG) {
+                    Logger.startScope("invoking remote " + methodName);
+                }
+                incCount(methodName, args);
+
+                output.writeObject(new Invocation(receiver, methodName, args));
+                output.flush();
+                result = waitForResult(false);
+
+                // result caching for selected methods
+                if ((args == null || args.length == 0) && cachedMethodNames.contains(methodName)) {
+                    cache.put(methodName, result);
+                }
+                return result;
+            } catch (Throwable t) {
+                t.printStackTrace();
+                throw t;
+            } finally {
+                if (DEBUG) {
+                    Logger.endScope(" = " + result);
+                }
+            }
+        }
+    }
+
+    /**
+     * Waits for the result of a remote method invocation. Invocations that should be executed in this VM might arrive
+     * while waiting for the result, and these invocations will be executed before again waiting fort he result.
+     */
+    public Object waitForResult(boolean eofExpected) throws IOException, ClassNotFoundException {
+        while (true) {
+            Object in;
+            try {
+                in = input.readObject();
+            } catch (EOFException e) {
+                if (eofExpected) {
+                    return null;
+                }
+                throw e;
+            }
+            if (in instanceof Result) {
+                return ((Result) in).result;
+            } else if (in instanceof RuntimeException) {
+                throw (RuntimeException) in;
+            } else if (in instanceof Throwable) {
+                throw new RuntimeException((Throwable) in);
+            }
+
+            Invocation invoke = (Invocation) in;
+            Method method = null;
+            for (Class<?> clazz = invoke.receiver.getClass(); clazz != null; clazz = clazz.getSuperclass()) {
+                for (Method m : clazz.getDeclaredMethods()) {
+                    if (invoke.methodName.equals(m.getName())) {
+                        method = m;
+                        break;
+                    }
+                }
+            }
+            if (method == null) {
+                Exception e = new UnsupportedOperationException("unknown method " + invoke.methodName);
+                e.printStackTrace();
+                output.writeObject(e);
+                output.flush();
+            } else {
+                Object result = null;
+                try {
+                    if (invoke.args == null) {
+                        if (DEBUG) {
+                            Logger.startScope("invoking local " + invoke.methodName);
+                        }
+                        result = method.invoke(invoke.receiver);
+                    } else {
+                        if (Logger.ENABLED && DEBUG) {
+                            StringBuilder str = new StringBuilder();
+                            str.append("invoking local " + invoke.methodName + "(");
+                            for (int i = 0; i < invoke.args.length; i++) {
+                                str.append(i == 0 ? "" : ", ");
+                                str.append(Logger.pretty(invoke.args[i]));
+                            }
+                            str.append(")");
+                            Logger.startScope(str.toString());
+                        }
+                        result = method.invoke(invoke.receiver, invoke.args);
+                    }
+                    result = new Result(result);
+                } catch (IllegalArgumentException e) {
+                    System.out.println("error while invoking " + invoke.methodName);
+                    e.getCause().printStackTrace();
+                    result = e.getCause();
+                } catch (InvocationTargetException e) {
+                    System.out.println("error while invoking " + invoke.methodName);
+                    e.getCause().printStackTrace();
+                    result = e.getCause();
+                } catch (IllegalAccessException e) {
+                    System.out.println("error while invoking " + invoke.methodName);
+                    e.getCause().printStackTrace();
+                    result = e.getCause();
+                } finally {
+                    if (DEBUG) {
+                        if (result instanceof Result) {
+                            Logger.endScope(" = " + ((Result) result).result);
+                        } else {
+                            Logger.endScope(" = " + result);
+                        }
+                    }
+                }
+                output.writeObject(result);
+                output.flush();
+            }
+        }
+    }
+
+    /**
+     * Sends a result without invoking a method, used by CompilationServer startup code.
+     */
+    public void sendResult(Object obj) throws IOException {
+        output.writeObject(new Result(obj));
+        output.flush();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/TemplateFlag.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,36 @@
+/*
+ * 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.max.graal.runtime;
+
+enum TemplateFlag {
+    NULL_CHECK, READ_BARRIER, WRITE_BARRIER, STORE_CHECK, BOUNDS_CHECK, GIVEN_LENGTH, INPUTS_DIFFERENT, INPUTS_SAME, STATIC_METHOD, SYNCHRONIZED;
+
+    private static final long FIRST_FLAG = 0x0000000100000000L;
+    public static final long FLAGS_MASK = 0x0000FFFF00000000L;
+    public static final long INDEX_MASK = 0x00000000FFFFFFFFL;
+
+    public long bits() {
+        assert ((FIRST_FLAG << ordinal()) & FLAGS_MASK) != 0;
+        return FIRST_FLAG << ordinal();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMEntries.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,105 @@
+/*
+ * 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.max.graal.runtime;
+
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * Entries into the HotSpot VM from Java code.
+ */
+public interface VMEntries {
+
+    // Checkstyle: stop
+
+    byte[] RiMethod_code(HotSpotMethodResolved method);
+
+    String RiMethod_signature(HotSpotMethodResolved method);
+
+    RiExceptionHandler[] RiMethod_exceptionHandlers(HotSpotMethodResolved method);
+
+    boolean RiMethod_hasBalancedMonitors(HotSpotMethodResolved method);
+
+    RiMethod RiMethod_uniqueConcreteMethod(HotSpotMethodResolved method);
+
+    int RiMethod_invocationCount(HotSpotMethodResolved method);
+
+    int RiMethod_exceptionProbability(HotSpotMethodResolved method, int bci);
+
+    RiTypeProfile RiMethod_typeProfile(HotSpotMethodResolved method, int bci);
+
+    double RiMethod_branchProbability(HotSpotMethodResolved method, int bci);
+
+    double[] RiMethod_switchProbability(HotSpotMethodResolved method, int bci);
+
+    RiType RiSignature_lookupType(String returnType, HotSpotTypeResolved accessingClass);
+
+    Object RiConstantPool_lookupConstant(long vmId, int cpi);
+
+    RiMethod RiConstantPool_lookupMethod(long vmId, int cpi, byte byteCode);
+
+    RiSignature RiConstantPool_lookupSignature(long vmId, int cpi);
+
+    RiType RiConstantPool_lookupType(long vmId, int cpi);
+
+    RiField RiConstantPool_lookupField(long vmId, int cpi, byte byteCode);
+
+    RiConstantPool RiType_constantPool(HotSpotTypeResolved klass);
+
+    void installMethod(HotSpotTargetMethod targetMethod);
+
+    long installStub(HotSpotTargetMethod targetMethod);
+
+    HotSpotVMConfig getConfiguration();
+
+    RiMethod RiType_resolveMethodImpl(HotSpotTypeResolved klass, String name, String signature);
+
+    boolean RiType_isSubtypeOf(HotSpotTypeResolved klass, RiType other);
+
+    RiType getPrimitiveArrayType(CiKind kind);
+
+    RiType RiType_arrayOf(HotSpotTypeResolved klass);
+
+    RiType RiType_componentType(HotSpotTypeResolved klass);
+
+    boolean RiType_isInitialized(HotSpotTypeResolved klass);
+
+    RiType getType(Class<?> javaClass);
+
+    void recordBailout(String reason);
+
+    RiType RiType_uniqueConcreteSubtype(HotSpotTypeResolved klass);
+
+    RiType RiType_superType(HotSpotTypeResolved klass);
+
+    int getArrayLength(CiConstant array);
+
+    boolean compareConstantObjects(CiConstant x, CiConstant y);
+
+    RiType getRiType(CiConstant constant);
+
+    RiField[] RiType_fields(HotSpotTypeResolved klass);
+
+    // Checkstyle: resume
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMEntriesNative.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,151 @@
+/*
+ * 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.max.graal.runtime;
+
+import java.lang.reflect.*;
+
+import com.oracle.max.graal.runtime.server.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * Entries into the HotSpot VM from Java code.
+ */
+public class VMEntriesNative implements VMEntries, Remote {
+
+    // Checkstyle: stop
+    @Override
+    public native byte[] RiMethod_code(HotSpotMethodResolved method);
+
+    @Override
+    public native String RiMethod_signature(HotSpotMethodResolved method);
+
+    @Override
+    public native RiExceptionHandler[] RiMethod_exceptionHandlers(HotSpotMethodResolved method);
+
+    @Override
+    public native boolean RiMethod_hasBalancedMonitors(HotSpotMethodResolved method);
+
+    @Override
+    public native RiMethod RiMethod_uniqueConcreteMethod(HotSpotMethodResolved method);
+
+    @Override
+    public native int RiMethod_invocationCount(HotSpotMethodResolved method);
+
+    @Override
+    public native int RiMethod_exceptionProbability(HotSpotMethodResolved method, int bci);
+
+    @Override
+    public native RiTypeProfile RiMethod_typeProfile(HotSpotMethodResolved method, int bci);
+
+    @Override
+    public native double RiMethod_branchProbability(HotSpotMethodResolved method, int bci);
+
+    @Override
+    public native double[] RiMethod_switchProbability(HotSpotMethodResolved method, int bci);
+
+    @Override
+    public native RiType RiSignature_lookupType(String returnType, HotSpotTypeResolved accessingClass);
+
+    @Override
+    public native Object RiConstantPool_lookupConstant(long vmId, int cpi);
+
+    @Override
+    public native RiMethod RiConstantPool_lookupMethod(long vmId, int cpi, byte byteCode);
+
+    @Override
+    public native RiSignature RiConstantPool_lookupSignature(long vmId, int cpi);
+
+    @Override
+    public native RiType RiConstantPool_lookupType(long vmId, int cpi);
+
+    @Override
+    public native RiField RiConstantPool_lookupField(long vmId, int cpi, byte byteCode);
+
+    @Override
+    public native RiConstantPool RiType_constantPool(HotSpotTypeResolved klass);
+
+    @Override
+    public native void installMethod(HotSpotTargetMethod targetMethod);
+
+    @Override
+    public native long installStub(HotSpotTargetMethod targetMethod);
+
+    @Override
+    public native HotSpotVMConfig getConfiguration();
+
+    @Override
+    public native RiMethod RiType_resolveMethodImpl(HotSpotTypeResolved klass, String name, String signature);
+
+    @Override
+    public native boolean RiType_isSubtypeOf(HotSpotTypeResolved klass, RiType other);
+
+    @Override
+    public native RiType getPrimitiveArrayType(CiKind kind);
+
+    @Override
+    public native RiType RiType_arrayOf(HotSpotTypeResolved klass);
+
+    @Override
+    public native RiType RiType_componentType(HotSpotTypeResolved klass);
+
+    @Override
+    public native RiType RiType_uniqueConcreteSubtype(HotSpotTypeResolved klass);
+
+    @Override
+    public native RiType RiType_superType(HotSpotTypeResolved klass);
+
+    @Override
+    public native boolean RiType_isInitialized(HotSpotTypeResolved klass);
+
+    @Override
+    public native RiType getType(Class<?> javaClass);
+
+    @Override
+    public native void recordBailout(String reason);
+
+    @Override
+    public int getArrayLength(CiConstant array) {
+        return Array.getLength(array.asObject());
+    }
+
+    @Override
+    public boolean compareConstantObjects(CiConstant x, CiConstant y) {
+        return x.asObject() == y.asObject();
+    }
+
+    @Override
+    public RiType getRiType(CiConstant constant) {
+        Object o = constant.asObject();
+        if (o == null) {
+            return null;
+        }
+        return getType(o.getClass());
+    }
+
+    @Override
+    public native RiField[] RiType_fields(HotSpotTypeResolved klass);
+
+    // Checkstyle: resume
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMExits.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,61 @@
+/*
+ * 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.max.graal.runtime;
+
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * Exits from the HotSpot VM into Java code.
+ */
+public interface VMExits {
+
+    void compileMethod(HotSpotMethodResolved method, int entryBCI) throws Throwable;
+
+    RiMethod createRiMethodUnresolved(String name, String signature, RiType holder);
+
+    RiSignature createRiSignature(String signature);
+
+    RiField createRiField(RiType holder, String name, RiType type, int offset, int flags);
+
+    RiType createRiType(long vmId, String name);
+
+    RiType createRiTypePrimitive(int basicType);
+
+    RiType createRiTypeUnresolved(String name);
+
+    RiConstantPool createRiConstantPool(long vmId);
+
+    CiConstant createCiConstant(CiKind kind, long value);
+
+    CiConstant createCiConstantFloat(float value);
+
+    CiConstant createCiConstantDouble(double value);
+
+    CiConstant createCiConstantObject(Object object);
+
+    void shutdownCompiler() throws Throwable;
+
+    void startCompiler();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMExitsNative.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,280 @@
+/*
+ * 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.max.graal.runtime;
+
+import java.io.*;
+import java.lang.management.*;
+import java.util.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.graph.*;
+import com.oracle.max.graal.runtime.logging.*;
+import com.oracle.max.graal.runtime.server.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * Exits from the HotSpot VM into Java code.
+ */
+public class VMExitsNative implements VMExits, Remote {
+
+    public static final boolean LogCompiledMethods = false;
+    public static boolean compileMethods = true;
+    private static boolean PrintGCStats = false;
+
+    private final Compiler compiler;
+
+    public final HotSpotTypePrimitive typeBoolean;
+    public final HotSpotTypePrimitive typeChar;
+    public final HotSpotTypePrimitive typeFloat;
+    public final HotSpotTypePrimitive typeDouble;
+    public final HotSpotTypePrimitive typeByte;
+    public final HotSpotTypePrimitive typeShort;
+    public final HotSpotTypePrimitive typeInt;
+    public final HotSpotTypePrimitive typeLong;
+    public final HotSpotTypePrimitive typeVoid;
+
+    public VMExitsNative(Compiler compiler) {
+        this.compiler = compiler;
+
+        typeBoolean = new HotSpotTypePrimitive(compiler, CiKind.Boolean);
+        typeChar = new HotSpotTypePrimitive(compiler, CiKind.Char);
+        typeFloat = new HotSpotTypePrimitive(compiler, CiKind.Float);
+        typeDouble = new HotSpotTypePrimitive(compiler, CiKind.Double);
+        typeByte = new HotSpotTypePrimitive(compiler, CiKind.Byte);
+        typeShort = new HotSpotTypePrimitive(compiler, CiKind.Short);
+        typeInt = new HotSpotTypePrimitive(compiler, CiKind.Int);
+        typeLong = new HotSpotTypePrimitive(compiler, CiKind.Long);
+        typeVoid = new HotSpotTypePrimitive(compiler, CiKind.Void);
+    }
+
+    private static Set<String> compiledMethods = new HashSet<String>();
+
+    public void startCompiler() {
+        // Make sure TTY is initialized here such that the correct System.out is used for TTY.
+        TTY.isSuppressed();
+    }
+
+    public void shutdownCompiler() throws Throwable {
+        compileMethods = false;
+
+        new Sandbox() {
+
+            @Override
+            public void run() {
+                if (GraalOptions.Meter) {
+
+                    GraalMetrics.print();
+                }
+                if (GraalOptions.Time) {
+                    GraalTimers.print();
+                }
+                if (PrintGCStats) {
+                    printGCStats();
+                }
+            }
+        }.start();
+    }
+
+    public abstract class Sandbox {
+
+        public void start() throws Throwable {
+            // (ls) removed output and error stream rewiring, this influences applications and, for example, makes dacapo tests fail.
+//            PrintStream oldOut = System.out;
+//            PrintStream oldErr = System.err;
+            run();
+//            System.setOut(oldOut);
+//            System.setErr(oldErr);
+        }
+
+        protected abstract void run() throws Throwable;
+    }
+
+    public static void printGCStats() {
+        long totalGarbageCollections = 0;
+        long garbageCollectionTime = 0;
+
+        for (GarbageCollectorMXBean gc : ManagementFactory.getGarbageCollectorMXBeans()) {
+            long count = gc.getCollectionCount();
+            if (count >= 0) {
+                totalGarbageCollections += count;
+            }
+
+            long time = gc.getCollectionTime();
+            if (time >= 0) {
+                garbageCollectionTime += time;
+            }
+        }
+
+        System.out.println("Total Garbage Collections: " + totalGarbageCollections);
+        System.out.println("Total Garbage Collection Time (ms): " + garbageCollectionTime);
+    }
+
+    @Override
+    public void compileMethod(final HotSpotMethodResolved method, final int entryBCI) throws Throwable {
+        if (!compileMethods) {
+            return;
+        }
+
+        new Sandbox() {
+            @Override
+            public void run() throws Throwable {
+                try {
+                    CiResult result = compiler.getCompiler().compileMethod(method, -1, null, null);
+                    if (LogCompiledMethods) {
+                        String qualifiedName = CiUtil.toJavaName(method.holder()) + "::" + method.name();
+                        compiledMethods.add(qualifiedName);
+                    }
+
+                    if (result.bailout() != null) {
+                        Throwable cause = result.bailout().getCause();
+                        if (!GraalOptions.QuietBailout && !(result.bailout() instanceof JSRNotSupportedBailout)) {
+                            StringWriter out = new StringWriter();
+                            result.bailout().printStackTrace(new PrintWriter(out));
+                            TTY.println("Bailout while compiling " + method + " :\n" + out.toString());
+                            if (cause != null) {
+                                Logger.info("Trace for cause: ");
+                                for (StackTraceElement e : cause.getStackTrace()) {
+                                    String current = e.getClassName() + "::" + e.getMethodName();
+                                    String type = "";
+                                    if (compiledMethods.contains(current)) {
+                                        type = "compiled";
+                                    }
+                                    Logger.info(String.format("%-10s %3d %s", type, e.getLineNumber(), current));
+                                }
+                            }
+                        }
+                        String s = result.bailout().getMessage();
+                        if (cause != null) {
+                            s = cause.getMessage();
+                        }
+                        compiler.getVMEntries().recordBailout(s);
+                    } else {
+                        HotSpotTargetMethod.installMethod(compiler, method, result.targetMethod());
+                    }
+                } catch (Throwable t) {
+                    StringWriter out = new StringWriter();
+                    t.printStackTrace(new PrintWriter(out));
+                    TTY.println("Compilation interrupted: (" + method + ")\n" + out.toString());
+                    throw t;
+                }
+            }
+        }.start();
+    }
+
+    @Override
+    public RiMethod createRiMethodUnresolved(String name, String signature, RiType holder) {
+        return new HotSpotMethodUnresolved(compiler, name, signature, holder);
+    }
+
+    @Override
+    public RiSignature createRiSignature(String signature) {
+        return new HotSpotSignature(compiler, signature);
+    }
+
+    @Override
+    public RiField createRiField(RiType holder, String name, RiType type, int offset, int flags) {
+        if (offset != -1) {
+            HotSpotTypeResolved resolved = (HotSpotTypeResolved) holder;
+            return resolved.createRiField(name, type, offset, flags);
+        }
+        return new HotSpotField(compiler, holder, name, type, offset, flags);
+    }
+
+    @Override
+    public RiType createRiType(long vmId, String name) {
+        throw new RuntimeException("not implemented");
+    }
+
+    @Override
+    public RiType createRiTypePrimitive(int basicType) {
+        switch (basicType) {
+            case 4:
+                return typeBoolean;
+            case 5:
+                return typeChar;
+            case 6:
+                return typeFloat;
+            case 7:
+                return typeDouble;
+            case 8:
+                return typeByte;
+            case 9:
+                return typeShort;
+            case 10:
+                return typeInt;
+            case 11:
+                return typeLong;
+            case 14:
+                return typeVoid;
+            default:
+                throw new IllegalArgumentException("Unknown basic type: " + basicType);
+        }
+    }
+
+    @Override
+    public RiType createRiTypeUnresolved(String name) {
+        return new HotSpotTypeUnresolved(compiler, name);
+    }
+
+    @Override
+    public RiConstantPool createRiConstantPool(long vmId) {
+        return new HotSpotConstantPool(compiler, vmId);
+    }
+
+    @Override
+    public CiConstant createCiConstant(CiKind kind, long value) {
+        if (kind == CiKind.Long) {
+            return CiConstant.forLong(value);
+        } else if (kind == CiKind.Int) {
+            return CiConstant.forInt((int) value);
+        } else if (kind == CiKind.Short) {
+            return CiConstant.forShort((short) value);
+        } else if (kind == CiKind.Char) {
+            return CiConstant.forChar((char) value);
+        } else if (kind == CiKind.Byte) {
+            return CiConstant.forByte((byte) value);
+        } else if (kind == CiKind.Boolean) {
+            return (value == 0) ? CiConstant.FALSE : CiConstant.TRUE;
+        } else {
+            throw new IllegalArgumentException();
+        }
+    }
+
+    @Override
+    public CiConstant createCiConstantFloat(float value) {
+        return CiConstant.forFloat(value);
+    }
+
+    @Override
+    public CiConstant createCiConstantDouble(double value) {
+        return CiConstant.forDouble(value);
+    }
+
+    @Override
+    public CiConstant createCiConstantObject(Object object) {
+        return CiConstant.forObject(object);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/logging/CountingProxy.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,102 @@
+/*
+ * 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.max.graal.runtime.logging;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.oracle.max.graal.runtime.server.*;
+
+/**
+ * A java.lang.reflect proxy that hierarchically logs all method invocations along with their parameters and return
+ * values.
+ */
+public class CountingProxy<T> implements InvocationHandler {
+
+    public static final boolean ENABLED = Boolean.valueOf(System.getProperty("graal.countcalls"));
+
+    private T delegate;
+
+    private Map<Method, Long> calls = new HashMap<Method, Long>();
+
+    public CountingProxy(T delegate) {
+        assert ENABLED;
+        System.out.println("Counting proxy for " + delegate.getClass().getSimpleName() + " created");
+        this.delegate = delegate;
+        proxies.add(this);
+    }
+
+    @Override
+    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+        int argCount = args == null ? 0 : args.length;
+        if (method.getParameterTypes().length != argCount) {
+            throw new RuntimeException("wrong parameter count");
+        }
+        final Object result;
+        long count = calls.containsKey(method) ? calls.get(method) : 0;
+        calls.put(method, count + 1);
+        try {
+            if (args == null) {
+                result = method.invoke(delegate);
+            } else {
+                result = method.invoke(delegate, args);
+            }
+        } catch (InvocationTargetException e) {
+            throw e.getCause();
+        }
+        return result;
+    }
+
+    public static <T> T getProxy(Class<T> interf, T delegate) {
+        Class<?>[] interfaces = ReplacingStreams.getAllInterfaces(delegate.getClass());
+        Object obj = Proxy.newProxyInstance(interf.getClassLoader(), interfaces, new CountingProxy<T>(delegate));
+        return interf.cast(obj);
+    }
+
+    private static ArrayList<CountingProxy> proxies = new ArrayList<CountingProxy>();
+
+    static {
+        if (ENABLED) {
+            Runtime.getRuntime().addShutdownHook(new Thread() {
+
+                @Override
+                public void run() {
+                    for (CountingProxy proxy : proxies) {
+                        proxy.print();
+                    }
+                }
+            });
+        }
+    }
+
+    protected void print() {
+        long sum = 0;
+        for (Map.Entry<Method, Long> entry : calls.entrySet()) {
+            Method method = entry.getKey();
+            long count = entry.getValue();
+            sum += count;
+            System.out.println(delegate.getClass().getSimpleName() + "." + method.getName() + ": " + count);
+        }
+        System.out.println(delegate.getClass().getSimpleName() + " calls: " + sum);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/logging/Logger.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,170 @@
+/*
+ * 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.max.graal.runtime.logging;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+/**
+ * Scoped logging class used to display the call hierarchy of VMEntries/VMExits calls.
+ */
+public class Logger {
+
+    public static final boolean ENABLED = Boolean.valueOf(System.getProperty("graal.debug"));
+    private static final int SPACING = 4;
+    private static Deque<Boolean> openStack = new LinkedList<Boolean>();
+    private static boolean open = false;
+    private static int level = 0;
+
+    private static final PrintStream out;
+
+    static {
+        PrintStream ps = null;
+        String filename = System.getProperty("graal.info_file");
+        if (filename != null && !"".equals(filename)) {
+            try {
+                ps = new PrintStream(new FileOutputStream(filename));
+            } catch (FileNotFoundException e) {
+                e.printStackTrace();
+                ps = null;
+            }
+        }
+        out = ps;
+        if (out != null) {
+            out.println("start: " + new Date());
+        }
+    }
+
+    public static void info(String message) {
+        if (ENABLED) {
+            log(message);
+        } else {
+            System.out.println(message);
+        }
+        if (out != null) {
+            out.println(message);
+            out.flush();
+        }
+    }
+
+    public static void log(String message) {
+        if (ENABLED) {
+            for (String line : message.split("\n")) {
+                if (open) {
+                    System.out.println("...");
+                    open = false;
+                }
+                System.out.print(space(level));
+                System.out.println(line);
+            }
+        }
+    }
+
+    public static void startScope(String message) {
+        if (ENABLED) {
+            if (open) {
+                System.out.println("...");
+                open = false;
+            }
+            System.out.print(space(level));
+            System.out.print(message);
+            openStack.push(open);
+            open = true;
+            level++;
+        }
+    }
+
+    public static void endScope(String message) {
+        if (ENABLED) {
+            level--;
+            if (open) {
+                System.out.println(message);
+            } else {
+                System.out.println(space(level) + "..." + message);
+            }
+            open = openStack.pop();
+        }
+    }
+
+    private static String[] spaces = new String[50];
+
+    private static String space(int count) {
+        assert count >= 0;
+        String result;
+        if (count >= spaces.length || spaces[count] == null) {
+            StringBuilder str = new StringBuilder();
+            for (int i = 0; i < count * SPACING; i++) {
+                str.append(' ');
+            }
+            result = str.toString();
+            if (count < spaces.length) {
+                spaces[count] = result;
+            }
+        } else {
+            result = spaces[count];
+        }
+        return result;
+    }
+
+    public static String pretty(Object value) {
+        if (value == null) {
+            return "null";
+        }
+
+        Class<?> klass = value.getClass();
+        if (value instanceof Void) {
+            return "void";
+        } else if (value instanceof String) {
+            return "\"" + value + "\"";
+        } else if (value instanceof Method) {
+            return "method \"" + ((Method) value).getName() + "\"";
+        } else if (value instanceof Class<?>) {
+            return "class \"" + ((Class<?>) value).getSimpleName() + "\"";
+        } else if (value instanceof Integer) {
+            if ((Integer) value < 10) {
+                return value.toString();
+            }
+            return value + " (0x" + Integer.toHexString((Integer) value) + ")";
+        } else if (value instanceof Long) {
+            if ((Long) value < 10) {
+                return value + "l";
+            }
+            return value + "l (0x" + Long.toHexString((Long) value) + "l)";
+        } else if (klass.isArray()) {
+            StringBuilder str = new StringBuilder();
+            int dimensions = 0;
+            while (klass.isArray()) {
+                dimensions++;
+                klass = klass.getComponentType();
+            }
+            str.append(klass.getSimpleName()).append('[').append(Array.getLength(value)).append(']');
+            for (int i = 1; i < dimensions; i++) {
+                str.append("[]");
+            }
+            return str.toString();
+        }
+
+        return value.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/logging/LoggingProxy.java	Wed Jul 27 17:32:44 2011 -0700
@@ -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.max.graal.runtime.logging;
+
+import java.lang.reflect.*;
+
+import com.oracle.max.graal.runtime.server.*;
+
+/**
+ * A java.lang.reflect proxy that hierarchically logs all method invocations along with their parameters and return values.
+ */
+public class LoggingProxy<T> implements InvocationHandler {
+
+    private T delegate;
+
+    public LoggingProxy(T delegate) {
+        this.delegate = delegate;
+    }
+
+    @Override
+    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+        int argCount = args == null ? 0 : args.length;
+        if (method.getParameterTypes().length != argCount) {
+            throw new RuntimeException("wrong parameter count");
+        }
+        StringBuilder str = new StringBuilder();
+        str.append(method.getReturnType().getSimpleName() + " " + method.getDeclaringClass().getSimpleName() + "." + method.getName() + "(");
+        for (int i = 0; i < argCount; i++) {
+            str.append(i == 0 ? "" : ", ");
+            str.append(Logger.pretty(args[i]));
+        }
+        str.append(")");
+        Logger.startScope(str.toString());
+        final Object result;
+        try {
+            if (args == null) {
+                result = method.invoke(delegate);
+            } else {
+                result = method.invoke(delegate, args);
+            }
+        } catch (InvocationTargetException e) {
+            Logger.endScope(" = Exception " + e.getMessage());
+            throw e.getCause();
+        }
+        Logger.endScope(" = " + Logger.pretty(result));
+        return result;
+    }
+
+    /**
+     * The object returned by this method will implement all interfaces that are implemented by delegate.
+     */
+    public static <T> T getProxy(Class<T> interf, T delegate) {
+        Class<?>[] interfaces = ReplacingStreams.getAllInterfaces(delegate.getClass());
+        Object obj = Proxy.newProxyInstance(interf.getClassLoader(), interfaces, new LoggingProxy<T>(delegate));
+        return interf.cast(obj);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/logging/package-info.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+/**
+ * Logging framework for the HotSpot CRI implementation.
+ *
+ * @author Lukas Stadler
+ * @author Thomas Wuerthinger
+ */
+package com.oracle.max.graal.runtime.logging;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/ArrayWriteBarrier.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,101 @@
+/*
+ * 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.max.graal.runtime.nodes;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class ArrayWriteBarrier extends WriteBarrier {
+    private static final int INPUT_COUNT = 2;
+    private static final int INPUT_OBJECT = 0;
+    private static final int INPUT_LOCATION = 1;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    /**
+     * The instruction that produces the object tested against null.
+     */
+     public Value object() {
+        return (Value) inputs().get(super.inputCount() + INPUT_OBJECT);
+    }
+
+    public void setObject(Value n) {
+        inputs().set(super.inputCount() + INPUT_OBJECT, n);
+    }
+
+    /**
+     * The instruction that produces the object tested against null.
+     */
+     public LocationNode location() {
+        return (LocationNode) inputs().get(super.inputCount() + INPUT_LOCATION);
+    }
+
+    public void setLocation(LocationNode n) {
+        inputs().set(super.inputCount() + INPUT_LOCATION, n);
+    }
+
+    public ArrayWriteBarrier(Value object, LocationNode index, Graph graph) {
+        super(INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.setObject(object);
+        this.setLocation(index);
+    }
+
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return (T) new LIRGenerator.LIRGeneratorOp() {
+                @Override
+                public void generate(Node n, LIRGenerator generator) {
+                    assert n == ArrayWriteBarrier.this;
+                    CiVariable temp = generator.newVariable(CiKind.Word);
+                    generator.lir().lea(location().createAddress(generator, object()), temp);
+                    ArrayWriteBarrier.this.generateBarrier(temp, generator);
+                }
+            };
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("field write barrier ").print(object());
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        ArrayWriteBarrier x = new ArrayWriteBarrier(null, null, into);
+        super.copyInto(x);
+        return x;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/CurrentThread.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,73 @@
+/*
+ * 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.max.graal.runtime.nodes;
+
+import com.oracle.max.asm.target.amd64.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class CurrentThread extends FloatingNode {
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+    private int threadObjectOffset;
+
+    public CurrentThread(int threadObjectOffset, Graph graph) {
+        super(CiKind.Object, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.threadObjectOffset = threadObjectOffset;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return (T) new LIRGenerator.LIRGeneratorOp() {
+                @Override
+                public void generate(Node n, LIRGenerator generator) {
+                    CurrentThread conv = (CurrentThread) n;
+                    CiValue result = generator.createResultVariable(conv);
+                    generator.lir().move(new CiAddress(CiKind.Object, AMD64.r15.asValue(CiKind.Word), threadObjectOffset), result);
+                }
+            };
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public boolean valueEqual(Node i) {
+        return i instanceof CurrentThread;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("currentThread");
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new CurrentThread(threadObjectOffset, into);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/FPConversionNode.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,92 @@
+/*
+ * 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.max.graal.runtime.nodes;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class FPConversionNode extends FloatingNode {
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_OBJECT = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    /**
+     * The instruction that produces the object tested against null.
+     */
+     public Value value() {
+        return (Value) inputs().get(super.inputCount() + INPUT_OBJECT);
+    }
+
+    public void setValue(Value n) {
+        inputs().set(super.inputCount() + INPUT_OBJECT, n);
+    }
+
+    public FPConversionNode(CiKind kind, Value value, Graph graph) {
+        super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.setValue(value);
+    }
+
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return (T) new LIRGenerator.LIRGeneratorOp() {
+                @Override
+                public void generate(Node n, LIRGenerator generator) {
+                    FPConversionNode conv = (FPConversionNode) n;
+                    CiValue reg = generator.createResultVariable(conv);
+                    CiValue value = generator.load(conv.value());
+                    CiValue tmp = generator.forceToSpill(value, conv.kind, false);
+                    generator.lir().move(tmp, reg);
+                }
+            };
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public boolean valueEqual(Node i) {
+        return i instanceof FPConversionNode && ((FPConversionNode) i).kind == kind;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("fp conversion node ").print(value());
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new FPConversionNode(kind, null, into);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/FieldWriteBarrier.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,88 @@
+/*
+ * 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.max.graal.runtime.nodes;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class FieldWriteBarrier extends WriteBarrier {
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_OBJECT = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    /**
+     * The instruction that produces the object tested against null.
+     */
+     public Value object() {
+        return (Value) inputs().get(super.inputCount() + INPUT_OBJECT);
+    }
+
+    public void setObject(Value n) {
+        inputs().set(super.inputCount() + INPUT_OBJECT, n);
+    }
+
+    public FieldWriteBarrier(Value object, Graph graph) {
+        super(INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.setObject(object);
+    }
+
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return (T) new LIRGenerator.LIRGeneratorOp() {
+                @Override
+                public void generate(Node n, LIRGenerator generator) {
+                    assert n == FieldWriteBarrier.this;
+                    CiVariable temp = generator.newVariable(CiKind.Word);
+                    generator.lir().move(generator.makeOperand(object()), temp);
+                    FieldWriteBarrier.this.generateBarrier(temp, generator);
+                }
+            };
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("field write barrier ").print(object());
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        FieldWriteBarrier x = new FieldWriteBarrier(null, into);
+        super.copyInto(x);
+        return x;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/WriteBarrier.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,55 @@
+/*
+ * 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.max.graal.runtime.nodes;
+
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.lir.*;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.runtime.*;
+import com.sun.cri.ci.*;
+
+
+public abstract class WriteBarrier extends FixedNodeWithNext {
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    public WriteBarrier(int inputCount, int successorCount, Graph graph) {
+        super(CiKind.Illegal, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+    }
+
+
+    protected void generateBarrier(CiValue temp, LIRGenerator generator) {
+        HotSpotVMConfig config = CompilerImpl.getInstance().getConfig();
+        generator.lir().unsignedShiftRight(temp, CiConstant.forInt(config.cardtableShift), temp, CiValue.IllegalValue);
+
+        long startAddress = config.cardtableStartAddress;
+        int displacement = 0;
+        if (((int) startAddress) == startAddress) {
+            displacement = (int) startAddress;
+        } else {
+            generator.lir().add(temp, CiConstant.forLong(config.cardtableStartAddress), temp);
+        }
+        generator.lir().move(CiConstant.FALSE, new CiAddress(CiKind.Boolean, temp, displacement), (LIRDebugInfo) null);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/package-info.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,31 @@
+/*
+ * 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 containing the runtime interface (defined in the CRI project) implementation for HotSpot.
+ * There is a class that bridges from the C++ to the Java side (VMExitsNative.java) and one that bridges
+ * from the Java to the C++ side (VMEntriesNative.java).
+ *
+ * @author Lukas Stadler
+ * @author Thomas Wuerthinger
+ */
+package com.oracle.max.graal.runtime;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/server/CompilationServer.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,123 @@
+/*
+ * 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.max.graal.runtime.server;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+import javax.net.*;
+
+import com.oracle.max.graal.runtime.*;
+import com.oracle.max.graal.runtime.Compiler;
+import com.oracle.max.graal.runtime.logging.*;
+
+/**
+ * Server side of the client/server compilation model. The server listens for connections on the hardcoded port 1199.
+ *
+ * @author Lukas Stadler
+ */
+public class CompilationServer implements Runnable {
+
+    public static void main(String[] args) throws Exception {
+        new CompilationServer(false).run();
+    }
+
+    public static interface ConnectionObserver {
+
+        void connectionStarted(Compiler compiler);
+
+        void connectionFinished(Compiler compiler);
+    }
+
+    private final boolean multiple;
+    private final ArrayList<ConnectionObserver> observers = new ArrayList<ConnectionObserver>();
+
+    /**
+     * Creates a new Compilation server. The server is activated by calling {@link #run()} directly or via a new
+     * {@link Thread}.
+     *
+     * @param multiple true if the server should server should serve an infinite amount of consecutive connections,
+     *            false if it should terminate after the first connection ends.
+     */
+    public CompilationServer(boolean multiple) {
+        this.multiple = multiple;
+        HotSpotOptions.setDefaultOptions();
+    }
+
+    public void addConnectionObserver(ConnectionObserver observer) {
+        observers.add(observer);
+    }
+
+    public void removeConnectionObserver(ConnectionObserver observer) {
+        observers.remove(observer);
+    }
+
+    public void run() {
+        final ServerSocket serverSocket;
+        try {
+            serverSocket = ServerSocketFactory.getDefault().createServerSocket(1199);
+        } catch (IOException e) {
+            throw new RuntimeException("Couldn't create compilation server", e);
+        }
+        do {
+            Socket socket = null;
+            try {
+                Logger.log("Compilation server ready, waiting for client to connect...");
+                socket = serverSocket.accept();
+                Logger.log("Connected to " + socket.getRemoteSocketAddress());
+
+                ReplacingStreams streams = new ReplacingStreams(socket.getOutputStream(), socket.getInputStream());
+
+                // get the VMEntries proxy from the client
+                VMEntries entries = (VMEntries) streams.getInvocation().waitForResult(false);
+
+                // return the initialized compiler to the client
+                Compiler compiler = CompilerImpl.initializeServer(entries);
+                compiler.getCompiler();
+                streams.getInvocation().sendResult(compiler);
+
+                for (ConnectionObserver observer : observers) {
+                    observer.connectionStarted(compiler);
+                }
+
+                streams.getInvocation().waitForResult(true);
+
+                for (ConnectionObserver observer : observers) {
+                    observer.connectionFinished(compiler);
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            } catch (ClassNotFoundException e) {
+                throw new RuntimeException(e);
+            } finally {
+                if (socket != null) {
+                    try {
+                        socket.close();
+                    } catch (IOException e) {
+                    }
+                }
+            }
+        } while (multiple);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/server/Remote.java	Wed Jul 27 17:32:44 2011 -0700
@@ -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.max.graal.runtime.server;
+
+
+public interface Remote {
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/server/ReplacingStreams.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,228 @@
+/*
+ * 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.max.graal.runtime.server;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.oracle.max.graal.runtime.*;
+import com.oracle.max.graal.runtime.Compiler;
+import com.sun.cri.ci.*;
+
+public class ReplacingStreams {
+
+    private IdentityHashMap<Object, Placeholder> objectMap = new IdentityHashMap<Object, Placeholder>();
+    private ArrayList<Object> objectList = new ArrayList<Object>();
+
+    private ReplacingOutputStream output;
+    private ReplacingInputStream input;
+
+    private InvocationSocket invocation;
+
+    public ReplacingStreams(OutputStream outputStream, InputStream inputStream) throws IOException {
+        output = new ReplacingOutputStream(new BufferedOutputStream(outputStream));
+        // required, because creating an ObjectOutputStream writes a header, but doesn't flush the stream
+        output.flush();
+        input = new ReplacingInputStream(new BufferedInputStream(inputStream));
+        invocation = new InvocationSocket(output, input);
+
+        addStaticObject(CiValue.IllegalValue);
+        addStaticObject(HotSpotProxy.DUMMY_CONSTANT_OBJ);
+    }
+
+    public void setInvocationSocket(InvocationSocket invocation) {
+        this.invocation = invocation;
+    }
+
+    public ReplacingOutputStream getOutput() {
+        return output;
+    }
+
+    public ReplacingInputStream getInput() {
+        return input;
+    }
+
+    public InvocationSocket getInvocation() {
+        return invocation;
+    }
+
+    private void addStaticObject(Object obj) {
+        int id = objectList.size();
+        objectList.add(obj);
+        objectMap.put(obj, new Placeholder(id));
+    }
+
+    public static class Placeholder implements Serializable {
+
+        public final int id;
+
+        public Placeholder(int id) {
+            this.id = id;
+        }
+
+        @Override
+        public String toString() {
+            return "#<" + id + ">";
+        }
+    }
+
+    public static class NewRemoteCallPlaceholder implements Serializable {
+
+        public final Class<?>[] interfaces;
+
+        public NewRemoteCallPlaceholder(Class<?>[] interfaces) {
+            this.interfaces = interfaces;
+        }
+    }
+
+    public static class NewDummyPlaceholder implements Serializable {
+    }
+
+    /**
+     * Replaces certain cir objects that cannot easily be made Serializable.
+     */
+    public class ReplacingInputStream extends ObjectInputStream {
+
+        private Compiler compiler;
+
+        public ReplacingInputStream(InputStream in) throws IOException {
+            super(in);
+            enableResolveObject(true);
+        }
+
+        public void setCompiler(Compiler compiler) {
+            this.compiler = compiler;
+        }
+
+        @Override
+        protected Object resolveObject(Object obj) throws IOException {
+            // see ReplacingInputStream.replaceObject for details on when these types of objects are created
+
+            if (obj instanceof Placeholder) {
+                Placeholder placeholder = (Placeholder) obj;
+                obj = objectList.get(placeholder.id);
+                return obj;
+            }
+
+            if (obj instanceof NewRemoteCallPlaceholder) {
+                NewRemoteCallPlaceholder newPlaceholder = (NewRemoteCallPlaceholder) obj;
+                Placeholder placeholder = new Placeholder(objectList.size());
+                obj = Proxy.newProxyInstance(getClass().getClassLoader(), newPlaceholder.interfaces, invocation.new Handler(placeholder));
+                objectMap.put(obj, placeholder);
+                objectList.add(obj);
+                return obj;
+            }
+
+            if (obj instanceof NewDummyPlaceholder) {
+                obj = new Placeholder(objectList.size());
+                objectMap.put(obj, (Placeholder) obj);
+                objectList.add(obj);
+                return obj;
+            }
+
+            return obj;
+        }
+    }
+
+    /**
+     * Replaces certain cir objects that cannot easily be made Serializable.
+     */
+    public class ReplacingOutputStream extends ObjectOutputStream {
+
+        public ReplacingOutputStream(OutputStream out) throws IOException {
+            super(out);
+            enableReplaceObject(true);
+        }
+
+        @Override
+        protected Object replaceObject(Object obj) throws IOException {
+            // is the object a known instance?
+            Placeholder placeholder = objectMap.get(obj);
+            if (placeholder != null) {
+                return placeholder;
+            }
+
+            // is the object an instance of a class that will always be executed remotely?
+            if (obj instanceof Remote) {
+                return createRemoteCallPlaceholder(obj);
+            }
+
+            // is the object a constant of object type?
+            if (obj.getClass() == CiConstant.class) {
+                CiConstant constant = (CiConstant) obj;
+                if (constant.kind != CiKind.Object) {
+                    return obj;
+                }
+                Object contents = constant.asObject();
+                if (contents == null) {
+                    return obj;
+                }
+                // don't replace if the object already is a placeholder
+                if (contents instanceof Placeholder || contents instanceof Long) {
+                    return obj;
+                }
+                placeholder = objectMap.get(contents);
+                if (placeholder != null) {
+                    return CiConstant.forObject(placeholder);
+                }
+                if (contents instanceof Remote) {
+                    return CiConstant.forObject(createRemoteCallPlaceholder(contents));
+                }
+                return CiConstant.forObject(createDummyPlaceholder(contents));
+            }
+            return obj;
+        }
+    }
+
+    public static Class<?>[] getAllInterfaces(Class<?> clazz) {
+        HashSet<Class< ? >> interfaces = new HashSet<Class<?>>();
+        getAllInterfaces(clazz, interfaces);
+        return interfaces.toArray(new Class<?>[interfaces.size()]);
+    }
+
+    private static void getAllInterfaces(Class<?> clazz, HashSet<Class<?>> interfaces) {
+        for (Class< ? > iface : clazz.getInterfaces()) {
+            if (!interfaces.contains(iface)) {
+                interfaces.add(iface);
+                getAllInterfaces(iface, interfaces);
+            }
+        }
+        if (clazz.getSuperclass() != null) {
+            getAllInterfaces(clazz.getSuperclass(), interfaces);
+        }
+    }
+
+    private Object createRemoteCallPlaceholder(Object obj) {
+        // collect all interfaces that this object's class implements (proxies only support interfaces)
+        objectMap.put(obj, new Placeholder(objectList.size()));
+        objectList.add(obj);
+        return new NewRemoteCallPlaceholder(getAllInterfaces(obj.getClass()));
+    }
+
+    public Object createDummyPlaceholder(Object obj) {
+        objectMap.put(obj, new Placeholder(objectList.size()));
+        objectList.add(obj);
+        return new NewDummyPlaceholder();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/server/package-info.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+/**
+ * Implementation of a compilation server socket that delegates incoming requests to Graal.
+ */
+package com.oracle.max.graal.runtime.server;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/hotspot/.cproject	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,661 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?fileVersion 4.0.0?>
+
+<cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
+	<storageModule moduleId="org.eclipse.cdt.core.settings">
+		<cconfiguration id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881">
+			<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881" moduleId="org.eclipse.cdt.core.settings" name="Default">
+				<externalSettings/>
+				<extensions>
+					<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+					<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+				</extensions>
+			</storageModule>
+			<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+				<configuration artifactName="hotspot" buildProperties="" description="" id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881" name="Default" parent="org.eclipse.cdt.build.core.emptycfg">
+					<folderInfo id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.305678577" name="/" resourcePath="">
+						<toolChain id="cdt.managedbuild.toolchain.gnu.base.1866612258" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.base">
+							<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.target.gnu.platform.base.2075405295" name="Debug Platform" osList="linux,hpux,aix,qnx" superClass="cdt.managedbuild.target.gnu.platform.base"/>
+							<builder arguments="${workspace_loc:/hotspot}/../../domake" autoBuildTarget="jvmg1" buildPath="${workspace_loc:/hotspot}/../../make" cleanBuildTarget="clean" command="bash" enableAutoBuild="true" enableCleanBuild="false" enabledIncrementalBuild="false" id="cdt.managedbuild.target.gnu.builder.base.81453037" incrementalBuildTarget="jvmg1" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" parallelizationNumber="1" superClass="cdt.managedbuild.target.gnu.builder.base">
+								<outputEntries>
+									<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="outputPath" name=""/>
+								</outputEntries>
+							</builder>
+							<tool id="cdt.managedbuild.tool.gnu.archiver.base.1094883386" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.base.1342888057" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.base">
+								<option id="gnu.cpp.compiler.option.include.paths.801956928" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths"/>
+								<option id="gnu.cpp.compiler.option.preprocessor.def.634868600" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" valueType="definedSymbols">
+									<listOptionValue builtIn="false" value="_LP64=1"/>
+									<listOptionValue builtIn="false" value="COMPILER1=1"/>
+									<listOptionValue builtIn="false" value="VM_LITTLE_ENDIAN=1"/>
+									<listOptionValue builtIn="false" value="ASSERT=1"/>
+									<listOptionValue builtIn="false" value="_REENTRANT=1"/>
+									<listOptionValue builtIn="false" value="DEBUG=1"/>
+									<listOptionValue builtIn="false" value="AMD64=1"/>
+								</option>
+								<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.866181452" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.compiler.base.1535888880" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base">
+								<option id="gnu.c.compiler.option.preprocessor.def.symbols.825962493" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" valueType="definedSymbols">
+									<listOptionValue builtIn="false" value="_LP64=1"/>
+									<listOptionValue builtIn="false" value="COMPILER1=1"/>
+									<listOptionValue builtIn="false" value="VM_LITTLE_ENDIAN=1"/>
+									<listOptionValue builtIn="false" value="ASSERT=1"/>
+									<listOptionValue builtIn="false" value="_REENTRANT=1"/>
+									<listOptionValue builtIn="false" value="DEBUG=1"/>
+									<listOptionValue builtIn="false" value="AMD64=1"/>
+								</option>
+								<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.906671119" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.linker.base.1271041307" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.base"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.linker.base.550499946" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.base">
+								<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.274517766" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
+									<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+									<additionalInput kind="additionalinput" paths="$(LIBS)"/>
+								</inputType>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.assembler.base.554053529" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.base">
+								<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1055083385" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+							</tool>
+						</toolChain>
+					</folderInfo>
+					<sourceEntries>
+						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
+					</sourceEntries>
+				</configuration>
+			</storageModule>
+			<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+			<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
+			<storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>
+			<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
+			<storageModule moduleId="scannerConfiguration">
+				<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+				<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+					<buildOutputProvider>
+						<openAction enabled="true" filePath=""/>
+						<parser enabled="true"/>
+					</buildOutputProvider>
+					<scannerInfoProvider id="specsFile">
+						<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+						<parser enabled="true"/>
+					</scannerInfoProvider>
+				</profile>
+				<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+					<buildOutputProvider>
+						<openAction enabled="true" filePath=""/>
+						<parser enabled="true"/>
+					</buildOutputProvider>
+					<scannerInfoProvider id="makefileGenerator">
+						<runAction arguments="-E -P -v -dD" command="" useDefault="true"/>
+						<parser enabled="true"/>
+					</scannerInfoProvider>
+				</profile>
+				<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+					<buildOutputProvider>
+						<openAction enabled="true" filePath=""/>
+						<parser enabled="true"/>
+					</buildOutputProvider>
+					<scannerInfoProvider id="specsFile">
+						<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+						<parser enabled="true"/>
+					</scannerInfoProvider>
+				</profile>
+				<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
+					<buildOutputProvider>
+						<openAction enabled="true" filePath=""/>
+						<parser enabled="true"/>
+					</buildOutputProvider>
+					<scannerInfoProvider id="specsFile">
+						<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
+						<parser enabled="true"/>
+					</scannerInfoProvider>
+				</profile>
+				<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
+					<buildOutputProvider>
+						<openAction enabled="true" filePath=""/>
+						<parser enabled="true"/>
+					</buildOutputProvider>
+					<scannerInfoProvider id="specsFile">
+						<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
+						<parser enabled="true"/>
+					</scannerInfoProvider>
+				</profile>
+				<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
+					<buildOutputProvider>
+						<openAction enabled="true" filePath=""/>
+						<parser enabled="true"/>
+					</buildOutputProvider>
+					<scannerInfoProvider id="specsFile">
+						<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/${specs_file}&quot;'" command="sh" useDefault="true"/>
+						<parser enabled="true"/>
+					</scannerInfoProvider>
+				</profile>
+				<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
+					<buildOutputProvider>
+						<openAction enabled="true" filePath=""/>
+						<parser enabled="true"/>
+					</buildOutputProvider>
+					<scannerInfoProvider id="specsFile">
+						<runAction arguments="-c 'g++ -E -P -v -dD &quot;${plugin_state_location}/specs.cpp&quot;'" command="sh" useDefault="true"/>
+						<parser enabled="true"/>
+					</scannerInfoProvider>
+				</profile>
+				<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
+					<buildOutputProvider>
+						<openAction enabled="true" filePath=""/>
+						<parser enabled="true"/>
+					</buildOutputProvider>
+					<scannerInfoProvider id="specsFile">
+						<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/specs.c&quot;'" command="sh" useDefault="true"/>
+						<parser enabled="true"/>
+					</scannerInfoProvider>
+				</profile>
+				<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.solaris.base.945602881;cdt.managedbuild.toolchain.gnu.solaris.base.945602881.305678577;cdt.managedbuild.tool.gnu.solaris.cpp.compiler.base.429326045;cdt.managedbuild.tool.gnu.cpp.compiler.input.1860785837">
+					<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"/>
+					<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="makefileGenerator">
+							<runAction arguments="-E -P -v -dD" command="" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/${specs_file}&quot;'" command="sh" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-c 'g++ -E -P -v -dD &quot;${plugin_state_location}/specs.cpp&quot;'" command="sh" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/specs.c&quot;'" command="sh" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+				</scannerConfigBuildInfo>
+				<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.solaris.base.945602881;cdt.managedbuild.toolchain.gnu.solaris.base.945602881.305678577;cdt.managedbuild.tool.gnu.cpp.compiler.base.1342888057;cdt.managedbuild.tool.gnu.cpp.compiler.input.866181452">
+					<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"/>
+					<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="makefileGenerator">
+							<runAction arguments="-E -P -v -dD" command="" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/${specs_file}&quot;'" command="sh" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-c 'g++ -E -P -v -dD &quot;${plugin_state_location}/specs.cpp&quot;'" command="sh" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/specs.c&quot;'" command="sh" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+				</scannerConfigBuildInfo>
+				<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.solaris.base.945602881;cdt.managedbuild.toolchain.gnu.solaris.base.945602881.305678577;cdt.managedbuild.tool.gnu.solaris.c.compiler.base.351149667;cdt.managedbuild.tool.gnu.c.compiler.input.820447325">
+					<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"/>
+					<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="makefileGenerator">
+							<runAction arguments="-E -P -v -dD" command="" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/${specs_file}&quot;'" command="sh" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-c 'g++ -E -P -v -dD &quot;${plugin_state_location}/specs.cpp&quot;'" command="sh" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/specs.c&quot;'" command="sh" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+				</scannerConfigBuildInfo>
+				<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.solaris.base.945602881;cdt.managedbuild.toolchain.gnu.solaris.base.945602881.388217325;cdt.managedbuild.tool.gnu.solaris.c.compiler.base.212558466;cdt.managedbuild.tool.gnu.c.compiler.input.1115218695">
+					<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"/>
+					<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="makefileGenerator">
+							<runAction arguments="-E -P -v -dD" command="" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/${specs_file}&quot;'" command="sh" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-c 'g++ -E -P -v -dD &quot;${plugin_state_location}/specs.cpp&quot;'" command="sh" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/specs.c&quot;'" command="sh" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+				</scannerConfigBuildInfo>
+				<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.solaris.base.945602881;cdt.managedbuild.toolchain.gnu.solaris.base.945602881.388217325;cdt.managedbuild.tool.gnu.solaris.cpp.compiler.base.377383651;cdt.managedbuild.tool.gnu.cpp.compiler.input.103897085">
+					<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"/>
+					<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="makefileGenerator">
+							<runAction arguments="-E -P -v -dD" command="" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/${specs_file}&quot;'" command="sh" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-c 'g++ -E -P -v -dD &quot;${plugin_state_location}/specs.cpp&quot;'" command="sh" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/specs.c&quot;'" command="sh" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+				</scannerConfigBuildInfo>
+				<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.solaris.base.945602881;cdt.managedbuild.toolchain.gnu.solaris.base.945602881.305678577;cdt.managedbuild.tool.gnu.c.compiler.base.1535888880;cdt.managedbuild.tool.gnu.c.compiler.input.906671119">
+					<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"/>
+					<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="makefileGenerator">
+							<runAction arguments="-E -P -v -dD" command="" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/${specs_file}&quot;'" command="sh" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-c 'g++ -E -P -v -dD &quot;${plugin_state_location}/specs.cpp&quot;'" command="sh" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+					<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
+						<buildOutputProvider>
+							<openAction enabled="true" filePath=""/>
+							<parser enabled="true"/>
+						</buildOutputProvider>
+						<scannerInfoProvider id="specsFile">
+							<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/specs.c&quot;'" command="sh" useDefault="true"/>
+							<parser enabled="true"/>
+						</scannerInfoProvider>
+					</profile>
+				</scannerConfigBuildInfo>
+			</storageModule>
+		</cconfiguration>
+	</storageModule>
+	<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+		<project id="hotspot.null.1712822257" name="hotspot"/>
+	</storageModule>
+</cproject>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/hotspot/.jcheck/conf	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,1 @@
+project=jdk7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/hotspot/.project	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>hotspot</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
+			<triggers>auto,</triggers>
+			<arguments>
+				<dictionary>
+					<key>?children?</key>
+					<value>?name?=outputEntries\|?children?=?name?=entry\\\\\\\|\\\|\||</value>
+				</dictionary>
+				<dictionary>
+					<key>?name?</key>
+					<value></value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.append_environment</key>
+					<value>true</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.autoBuildTarget</key>
+					<value>jvmg1</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.buildArguments</key>
+					<value>${workspace_loc:/hotspot}/../../domake</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.buildCommand</key>
+					<value>bash</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.buildLocation</key>
+					<value>${workspace_loc:/hotspot}/../../make</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.cleanBuildTarget</key>
+					<value>clean</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.contents</key>
+					<value>org.eclipse.cdt.make.core.activeConfigSettings</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.enableAutoBuild</key>
+					<value>true</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.enableCleanBuild</key>
+					<value>false</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.enableFullBuild</key>
+					<value>false</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.fullBuildTarget</key>
+					<value>jvmg1</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.stopOnError</key>
+					<value>true</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>
+					<value>false</value>
+				</dictionary>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
+			<triggers>full,incremental,</triggers>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.cdt.core.cnature</nature>
+		<nature>org.eclipse.cdt.core.ccnature</nature>
+		<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
+		<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
+	</natures>
+	<linkedResources>
+		<link>
+			<name>cpu</name>
+			<type>2</type>
+			<locationURI>PARENT-2-PROJECT_LOC/src/cpu/x86</locationURI>
+		</link>
+		<link>
+			<name>generated</name>
+			<type>2</type>
+			<locationURI>PARENT-2-PROJECT_LOC/build/linux/linux_amd64_compiler1/generated</locationURI>
+		</link>
+		<link>
+			<name>os</name>
+			<type>2</type>
+			<locationURI>PARENT-2-PROJECT_LOC/src/os/linux</locationURI>
+		</link>
+		<link>
+			<name>os_cpu</name>
+			<type>2</type>
+			<locationURI>PARENT-2-PROJECT_LOC/src/os_cpu/linux_x86</locationURI>
+		</link>
+		<link>
+			<name>vm</name>
+			<type>2</type>
+			<locationURI>PARENT-2-PROJECT_LOC/src/share/vm</locationURI>
+		</link>
+	</linkedResources>
+</projectDescription>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/hotspot/.settings/org.eclipse.cdt.core.prefs	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,152 @@
+#Wed Sep 01 16:57:34 PDT 2010
+eclipse.preferences.version=1
+org.eclipse.cdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.cdt.core.formatter.alignment_for_base_clause_in_type_declaration=80
+org.eclipse.cdt.core.formatter.alignment_for_compact_if=0
+org.eclipse.cdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.cdt.core.formatter.alignment_for_declarator_list=16
+org.eclipse.cdt.core.formatter.alignment_for_enumerator_list=48
+org.eclipse.cdt.core.formatter.alignment_for_expression_list=0
+org.eclipse.cdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.cdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.cdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.cdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.cdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.cdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.cdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.cdt.core.formatter.brace_position_for_namespace_declaration=end_of_line
+org.eclipse.cdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.cdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.cdt.core.formatter.compact_else_if=true
+org.eclipse.cdt.core.formatter.continuation_indentation=2
+org.eclipse.cdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.cdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.cdt.core.formatter.indent_access_specifier_compare_to_type_header=false
+org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_access_specifier=true
+org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_namespace_header=false
+org.eclipse.cdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.cdt.core.formatter.indent_declaration_compare_to_template_header=false
+org.eclipse.cdt.core.formatter.indent_empty_lines=false
+org.eclipse.cdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.cdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_switch=true
+org.eclipse.cdt.core.formatter.indentation.size=2
+org.eclipse.cdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.cdt.core.formatter.insert_new_line_after_template_declaration=do not insert
+org.eclipse.cdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.cdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.cdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.cdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.cdt.core.formatter.insert_new_line_before_identifier_in_function_declaration=do not insert
+org.eclipse.cdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.cdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.cdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.cdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_arguments=insert
+org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_parameters=insert
+org.eclipse.cdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.cdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.cdt.core.formatter.insert_space_after_colon_in_base_clause=insert
+org.eclipse.cdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.cdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.cdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.cdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.cdt.core.formatter.insert_space_after_comma_in_base_types=insert
+org.eclipse.cdt.core.formatter.insert_space_after_comma_in_declarator_list=insert
+org.eclipse.cdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.cdt.core.formatter.insert_space_after_comma_in_expression_list=insert
+org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_arguments=insert
+org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_parameters=insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_arguments=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_parameters=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_bracket=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_exception_specification=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.cdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.cdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.cdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_arguments=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_parameters=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_bracket=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_exception_specification=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_colon_in_base_clause=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.cdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_comma_in_base_types=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_comma_in_declarator_list=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_comma_in_expression_list=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_arguments=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_parameters=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_arguments=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_parameters=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_namespace_declaration=insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_bracket=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_exception_specification=insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.cdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.cdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.cdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.cdt.core.formatter.insert_space_between_empty_brackets=do not insert
+org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_exception_specification=do not insert
+org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.cdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.cdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.cdt.core.formatter.keep_imple_if_on_one_line=true
+org.eclipse.cdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.cdt.core.formatter.lineSplit=160
+org.eclipse.cdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.cdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.cdt.core.formatter.tabulation.char=space
+org.eclipse.cdt.core.formatter.tabulation.size=2
+org.eclipse.cdt.core.formatter.use_tabs_only_for_leading_indentations=false
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/hotspot/.settings/org.eclipse.cdt.ui.prefs	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,4 @@
+#Wed Sep 01 16:21:02 PDT 2010
+eclipse.preferences.version=1
+formatter_profile=_hotspotStyle
+formatter_settings_version=1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/hotspot/.settings/org.eclipse.core.runtime.prefs	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,5 @@
+#Wed Sep 01 16:13:40 PDT 2010
+content-types/enabled=true
+content-types/org.eclipse.cdt.core.cHeader/file-extensions=hpp,incl
+content-types/org.eclipse.cdt.core.cxxSource/file-extensions=cpp
+eclipse.preferences.version=1
--- a/make/Makefile	Tue Jun 28 10:57:38 2011 -0700
+++ b/make/Makefile	Wed Jul 27 17:32:44 2011 -0700
@@ -166,13 +166,9 @@
 	@$(ECHO) "No compiler1 ($(VM_TARGET)) for ARCH_DATA_MODEL=$(ARCH_DATA_MODEL)"
   endif
 else
-  ifeq ($(ARCH_DATA_MODEL), 32)
 	$(CD) $(OUTPUTDIR); \
 	    $(MAKE) -f $(ABS_OS_MAKEFILE) \
 		      $(MAKE_ARGS) $(VM_TARGET)
-  else
-	@$(ECHO) "No compiler1 ($(VM_TARGET)) for ARCH_DATA_MODEL=$(ARCH_DATA_MODEL)"
-  endif
 endif
 
 # Build compiler2 (server) rule, different for platforms
--- a/make/windows/build_vm_def.sh	Tue Jun 28 10:57:38 2011 -0700
+++ b/make/windows/build_vm_def.sh	Wed Jul 27 17:32:44 2011 -0700
@@ -54,6 +54,7 @@
 CAT="$MKS_HOME/cat.exe"
 RM="$MKS_HOME/rm.exe"
 DUMPBIN="link.exe /dump"
+export VS_UNICODE_OUTPUT= 
 
 # When called from IDE the first param should contain the link version, otherwise may be nill
 if [ "x$1" != "x" ]; then
--- a/make/windows/create.bat	Tue Jun 28 10:57:38 2011 -0700
+++ b/make/windows/create.bat	Wed Jul 27 17:32:44 2011 -0700
@@ -37,10 +37,10 @@
 REM that "grep" be accessible on the PATH. An MKS install does this.
 REM 
 
-cl 2>NUL >NUL
-if %errorlevel% == 0 goto nexttest
-echo Make sure cl.exe is in your PATH before running this script.
-goto end
+rem cl 2>NUL >NUL
+rem if %errorlevel% == 0 goto nexttest
+rem echo Make sure cl.exe is in your PATH before running this script.
+rem goto end
 
 :nexttest
 grep -V 2>NUL >NUL
@@ -52,6 +52,8 @@
 :testit
 cl 2>&1 | grep "x64" >NUL
 if %errorlevel% == 0 goto amd64
+cl 2>&1 | grep "x64" >NUL
+if %errorlevel% == 0 goto amd64
 set ARCH=x86
 set BUILDARCH=i486
 set Platform_arch=x86
--- a/make/windows/makefiles/projectcreator.make	Tue Jun 28 10:57:38 2011 -0700
+++ b/make/windows/makefiles/projectcreator.make	Wed Jul 27 17:32:44 2011 -0700
@@ -87,8 +87,8 @@
         -jdkTargetRoot $(HOTSPOTJDKDIST) \
         -define ALIGN_STACK_FRAMES \
         -define VM_LITTLE_ENDIAN \
-        -prelink  "" "Generating vm.def..." "cd $(HOTSPOTBUILDSPACE)\%f\%b	set HOTSPOTMKSHOME=$(HOTSPOTMKSHOME)	$(HOTSPOTMKSHOME)\sh $(HOTSPOTWORKSPACE)\make\windows\build_vm_def.sh $(LINK_VER)" \
-        -postbuild "" "Building hotspot.exe..." "cd $(HOTSPOTBUILDSPACE)\%f\%b	set HOTSPOTMKSHOME=$(HOTSPOTMKSHOME)	nmake -f $(HOTSPOTWORKSPACE)\make\windows\projectfiles\common\Makefile LOCAL_MAKE=$(HOTSPOTBUILDSPACE)\%f\local.make JAVA_HOME=$(HOTSPOTJDKDIST) launcher" \
+        -prelink  "" "Generating vm.def..." "cd %o	set HOTSPOTMKSHOME=$(HOTSPOTMKSHOME)	$(HOTSPOTMKSHOME)\sh $(HOTSPOTWORKSPACE)\make\windows\build_vm_def.sh $(LINK_VER)" \
+        -postbuild "" "Building hotspot.exe..." "cd %o	HOTSPOTMKSHOME=$(HOTSPOTMKSHOME)	nmake -f $(HOTSPOTWORKSPACE)\make\windows\projectfiles\common\Makefile LOCAL_MAKE=$(HOTSPOTBUILDSPACE)\%f\local.make JAVA_HOME=$(HOTSPOTJDKDIST) launcher" \
         -ignoreFile jsig.c \
         -ignoreFile jvmtiEnvRecommended.cpp \
         -ignoreFile jvmtiEnvStub.cpp \
--- a/make/windows/makefiles/vm.make	Tue Jun 28 10:57:38 2011 -0700
+++ b/make/windows/makefiles/vm.make	Wed Jul 27 17:32:44 2011 -0700
@@ -152,6 +152,7 @@
 VM_PATH=$(VM_PATH);../generated/adfiles
 VM_PATH=$(VM_PATH);../generated/jvmtifiles
 VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/c1
+VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/c1x
 VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/compiler
 VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/code
 VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/interpreter
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/perf/benchmarktool.py	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,154 @@
+import subprocess
+import os
+import re
+import sys
+import argparse
+
+DEFAULT_DACAPO_OPTS = " -XX:MaxPermSize=512m -Xms1g -Xmx2g "
+DEFAULT_SCIMARK_OPTS = " -Xms32m -Xmx100m "
+
+def runBash(cmd):
+    p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+    return p.stdout
+
+def s2msString(floatString):
+    return str(round(float(floatString)*1000))
+
+# Raw String Notation (r"") : \ instead of \\
+graalTime = re.compile(r"Total compilation time\s+:\s+([0-9]+\.[0-9]+) s")
+graalSubTime = re.compile(r"([a-zA-Z0-9_ ]+)\s+:\s+([0-9]+\.[0-9]+) s \([0-9 ][0-9]\.[0-9]{2}%\)")
+
+def matchGraalTime(string, csvOutput, csvOutputLine, writeHeaderAt):
+    match1 = graalTime.search(string)
+    match2 = graalSubTime.search(string)
+    if match1:
+        if csvOutputLine == writeHeaderAt:
+            csvOutput[0].append('graal total')
+        print('Graal total time: '+ s2msString(match1.group(1)))
+        csvOutput[csvOutputLine].append(s2msString(match1.group(1)))
+    elif match2:
+        if csvOutputLine == writeHeaderAt:
+            csvOutput[0].append(match2.group(1).strip())
+        print('Graal specific time: '+match2.group(1)+': '+s2msString(match2.group(2)))
+        csvOutput[csvOutputLine].append(s2msString(match2.group(2)))
+    else:
+        print('# '+string)
+
+def writeout(outputFile, csvOutput):
+    for csvLine in csvOutput :
+        outputFile.write(';'.join(csvLine)+';'+os.linesep)
+
+def main():
+    # Check for environment variables
+    if os.getenv('JDK7') is None:
+        print('Environment variable JDK7 is not defined.')
+        return 1
+    if os.getenv('DACAPO') is None:
+        print('Environment variable DACAPO is not defined. It must point to a directory with the DaCapo benchmark jar.')
+        return 1
+    if os.getenv('SCIMARK') is None:
+        print('Environment variable SCIMARK is not defined. It must point to a directory with the SciMark benchmark jar.')
+        return 1
+    if os.getenv('REFERENCE_JDK') is None:
+        print('Environment variable REFERENCE_JDK is not defined.')
+        return 1
+    
+    # Option parsing
+    parser = argparse.ArgumentParser(description='Automated DaCapo and Scimark bechmarks')
+    parser.add_argument('-a', '-all', help='run all benchmarks for all compilers', action='store_true')
+    parser.add_argument('-c', type=str, help='compiler to use', default='graal', choices=['client', 'server', 'graal'], required=False)
+    parser.add_argument('-n', type=int, help='number of DaCapo benchmarks to run', default=10)
+    parser.add_argument('-o', type=str, help='graalVM options(quoted!)', default='')
+    parser.add_argument('-runonly', type=str, help='run specified benchmark only', default='all')
+    options = parser.parse_args()
+    compilerFlags = {'graal' : '-client -graal -G:+Time -XX:-GraalBailoutIsFatal -G:QuietBailout ',
+        'client' : '-client',
+        'server' : '-server'}
+
+    if options.a: 
+        compilers = ['graal', 'client', 'server']
+    else:
+        compilers = [options.c]
+    
+    for compiler in compilers:
+    
+        outputFile = open(compiler+'.csv', 'w')
+    
+        # DaCapo Benchmarks
+        if compiler == 'graal':
+            vm = os.environ['JDK7']
+        else :
+            vm = os.environ['REFERENCE_JDK']
+        
+        cmd = '"' + vm + '/bin/java" ' + compilerFlags[compiler] + ' -d64 ' + DEFAULT_DACAPO_OPTS + options.o + ' -classpath ' + \
+            os.environ['DACAPO'] + '/dacapo-9.12-bach.jar Harness -n ' + str(options.n) + ' '
+        benchmarks = runBash('java -jar ' + os.environ['DACAPO'] + '/dacapo-9.12-bach.jar -l').read().decode().split(' ')
+    
+        benchmarkTime = re.compile(r"===== DaCapo 9\.12 ([a-zA-Z0-9_]+) ((PASSED)|(completed warmup [0-9]+)) in ([0-9]+) msec =====")
+    
+        csvOutput = [['benchmark', 'type', 'time']]
+        csvOutputLine = 0
+        for benchmark in benchmarks:
+            if options.runonly != 'all' and benchmark != options.runonly:
+                continue
+            nRuns = 0
+            dcOutput = runBash(cmd + benchmark)
+            while True:
+                line = dcOutput.readline().decode()
+                if not line:
+                    break
+                line = line.strip()
+                match = benchmarkTime.search(line)
+                if match:
+                    csvOutputLine = csvOutputLine + 1
+                    nRuns = nRuns + 1
+                    csvOutput.append(list())
+                    csvOutput[csvOutputLine].append(str(nRuns))
+                    print('Benchmark type: '+match.group(1))
+                    print('Benchmark time: '+match.group(5))
+                    csvOutput[csvOutputLine].append(match.group(1))
+                    csvOutput[csvOutputLine].append(match.group(5))
+                else:
+                    matchGraalTime(line, csvOutput, csvOutputLine, options.n)
+                    
+            if nRuns < options.n:
+                csvOutputLine = csvOutputLine + (options.n - nRuns)
+                for i in range(options.n - nRuns):
+                    csvOutput.append([str(nRuns + i), benchmark, '0'])
+    
+        writeout(outputFile, csvOutput)
+    
+        if options.runonly != 'all' and options.runonly != 'scimark':
+            outputFile.close()
+            return 0
+        
+        # Scimark Benchmarks
+        writeout(outputFile, [['']])
+        cmd = '"' + vm + '/bin/java" ' + compilerFlags[compiler] + ' -d64 ' + DEFAULT_SCIMARK_OPTS + options.o + \
+            ' -Xbootclasspath/a:' + os.environ['SCIMARK'] + '/scimark2lib.jar jnt.scimark2.commandline'
+    
+        benchmarkScore = re.compile(r"([a-zA-Z0-9_\(\),= ]+):\s+([0-9]+\.[0-9]+)$")
+    
+        csvOutput = [['run'],[]]
+        scOutput = runBash(cmd)
+        while True:
+            line = scOutput.readline().decode()
+            if not line:
+                break
+            line = line.strip()
+            match = benchmarkScore.search(line)
+            if match:
+                print('Scimark '+match.group(1)+' score: '+match.group(2))
+                csvOutput[0].append(match.group(1).strip())
+                csvOutput[1].append(match.group(2))
+            else:
+                matchGraalTime(line,csvOutput, 1, 1)
+    
+        writeout(outputFile, csvOutput)
+        outputFile.close()
+        
+    return 0
+
+#This idiom means the below code only runs when executed from command line
+if __name__ == '__main__':
+    sys.exit(main())
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runalldacapo.sh	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,15 @@
+#!/bin/bash
+bash rundacapo.sh avrora
+bash rundacapo.sh batik
+bash rundacapo.sh eclipse
+bash rundacapo.sh fop
+bash rundacapo.sh h2
+bash rundacapo.sh jython
+bash rundacapo.sh luindex
+bash rundacapo.sh lusearch
+bash rundacapo.sh pmd
+bash rundacapo.sh sunflow
+bash rundacapo.sh tomcat
+bash rundacapo.sh tradebeans
+bash rundacapo.sh tradesoap
+bash rundacapo.sh xalan
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runavrora.sh	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,20 @@
+#!/bin/bash
+if [ -z "${JDK7}" ]; then
+  echo "JDK7 is not defined."
+  exit 1;
+fi
+if [ -z "${MAXINE}" ]; then
+  echo "MAXINE is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${GRAAL}" ]; then
+  echo "GRAAL is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${DACAPO}" ]; then
+  echo "DACAPO is not defined. It must point to a Dacapo benchmark directory."
+  exit 1;
+fi
+COMMAND="${JDK7}/bin/java -client -d64 -graal -Xms1g -Xmx2g -esa -classpath ${DACAPO}/dacapo-9.12-bach.jar -XX:-GraalBailoutIsFatal -G:-QuietBailout $* Harness --preserve -n 20 avrora"
+echo $COMMAND
+$COMMAND
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runbootstrap.sh	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,14 @@
+#!/bin/bash
+if [ -z "${JDK7}" ]; then
+  echo "JDK7 is not defined."
+  exit 1;
+fi
+if [ -z "${MAXINE}" ]; then
+  echo "MAXINE is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${GRAAL}" ]; then
+  echo "GRAAL is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+${JDK7}/bin/java -client -d64 -graal $* -version 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rundacapo.sh	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,18 @@
+#!/bin/bash
+if [ -z "${JDK7}" ]; then
+  echo "JDK7 is not defined."
+  exit 1;
+fi
+if [ -z "${MAXINE}" ]; then
+  echo "MAXINE is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${GRAAL}" ]; then
+  echo "GRAAL is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${DACAPO}" ]; then
+  echo "DACAPO is not defined. It must point to a Dacapo benchmark directory."
+  exit 1;
+fi
+${JDK7}/bin/java -client -d64 -graal -XX:-GraalBailoutIsFatal -XX:MaxPermSize=512m -XX:+PrintCompilation -Xms1g -Xmx2g -esa -classpath ${DACAPO}/dacapo-9.12-bach.jar Harness --preserve $*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runeclipse.sh	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,21 @@
+#!/bin/bash
+if [ -z "${JDK7}" ]; then
+  echo "JDK7 is not defined."
+  exit 1;
+fi
+if [ -z "${MAXINE}" ]; then
+  echo "MAXINE is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${GRAAL}" ]; then
+  echo "GRAAL is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${DACAPO}" ]; then
+  echo "DACAPO is not defined. It must point to a Dacapo benchmark directory."
+  exit 1;
+fi
+COMMAND="${JDK7}/bin/java -client -d64 -graal -Xms1g -Xmx2g -esa -classpath ${DACAPO}/dacapo-9.12-bach.jar -XX:-GraalBailoutIsFatal -G:-QuietBailout $* Harness --preserve -n 5 eclipse"
+echo $COMMAND
+$COMMAND
+echo $COMMAND
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runexamples.sh	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,21 @@
+#!/bin/bash
+if [ -z "${JDK7}" ]; then
+  echo "JDK7 is not defined."
+  exit 1;
+fi
+if [ -z "${MAXINE}" ]; then
+  echo "MAXINE is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${GRAAL}" ]; then
+  echo "GRAAL is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${DACAPO}" ]; then
+  echo "DACAPO is not defined. It must point to a Dacapo benchmark directory."
+  exit 1;
+fi
+ant -f create_examples.xml
+COMMAND="${JDK7}/bin/java -client -d64 -graal -Xms1g -Xmx2g -esa -G:Extend -Xcomp -XX:CompileOnly=examples $* -jar examples.jar"
+echo $COMMAND
+$COMMAND
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runexamplescompare.sh	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,27 @@
+#!/bin/bash
+if [ -z "${JDK7}" ]; then
+  echo "JDK7 is not defined."
+  exit 1;
+fi
+if [ -z "${MAXINE}" ]; then
+  echo "MAXINE is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${GRAAL}" ]; then
+  echo "GRAAL is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${DACAPO}" ]; then
+  echo "DACAPO is not defined. It must point to a Dacapo benchmark directory."
+  exit 1;
+fi
+ant -f create_examples.xml
+COMMAND="${JDK7}/bin/java -client -d64 -graal -Xms1g -Xmx2g -esa -G:Extend -Xcomp -XX:CompileOnly=examples $* -jar examples.jar"
+echo $COMMAND
+$COMMAND
+COMMAND="${JDK7}/bin/java -client -d64 -Xms1g -Xmx2g -esa -Xcomp -XX:CompileOnly=examples $* -jar examples.jar"
+echo $COMMAND
+$COMMAND
+COMMAND="${JDK7}/bin/java -server -d64 -Xms1g -Xmx2g -esa -Xcomp -XX:CompileOnly=examples $* -jar examples.jar"
+echo $COMMAND
+$COMMAND
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runfilter.sh	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,21 @@
+#!/bin/bash
+if [ -z "${JDK7}" ]; then
+  echo "JDK7 is not defined."
+  exit 1;
+fi
+if [ -z "${MAXINE}" ]; then
+  echo "MAXINE is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${GRAAL}" ]; then
+  echo "GRAAL is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ $# -lt 1 ]; then
+  echo "You must provide at least a filter option"
+  exit 1;
+fi
+FILTER=$1
+shift 1
+TESTDIR=${MAXINE}/com.oracle.max.vm/test
+${JDK7}/bin/java -client -d64 -graal -ea -esa -Xcomp -XX:+PrintCompilation -XX:CompileOnly=jtt -Xbootclasspath/p:"${MAXINE}/com.oracle.max.vm/bin" -Xbootclasspath/p:"${MAXINE}/com.oracle.max.base/bin" $@ test.com.sun.max.vm.compiler.JavaTester -filter=${FILTER} -verbose=1 -gen-run-scheme=false -run-scheme-package=all $@ ${TESTDIR}/jtt/bytecode ${TESTDIR}/jtt/except ${TESTDIR}/jtt/hotpath ${TESTDIR}/jtt/jdk ${TESTDIR}/jtt/lang ${TESTDIR}/jtt/loop ${TESTDIR}/jtt/micro ${TESTDIR}/jtt/optimize ${TESTDIR}/jtt/reflect ${TESTDIR}/jtt/threads ${TESTDIR}/jtt/reflect ${TESTDIR}/jtt/hotspot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runfop.sh	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,18 @@
+#!/bin/bash
+if [ -z "${JDK7}" ]; then
+  echo "JDK7 is not defined."
+  exit 1;
+fi
+if [ -z "${MAXINE}" ]; then
+  echo "MAXINE is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${GRAAL}" ]; then
+  echo "GRAAL is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${DACAPO}" ]; then
+  echo "DACAPO is not defined. It must point to a Dacapo benchmark directory."
+  exit 1;
+fi
+${JDK7}/bin/java -client -d64 -graal -Xms1g -Xmx2g -esa -classpath ${DACAPO}/dacapo-9.12-bach.jar -XX:-GraalBailoutIsFatal $* Harness --preserve -n 20 fop 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runjython.sh	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,20 @@
+#!/bin/bash
+if [ -z "${JDK7}" ]; then
+  echo "JDK7 is not defined."
+  exit 1;
+fi
+if [ -z "${MAXINE}" ]; then
+  echo "MAXINE is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${GRAAL}" ]; then
+  echo "GRAAL is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${DACAPO}" ]; then
+  echo "DACAPO is not defined. It must point to a Dacapo benchmark directory."
+  exit 1;
+fi
+COMMAND="${JDK7}/bin/java -client -d64 -graal -Xms1g -Xmx2g -esa -classpath ${DACAPO}/dacapo-9.12-bach.jar -XX:-GraalBailoutIsFatal -G:-QuietBailout $* Harness --preserve -n 20 jython"
+echo $COMMAND
+$COMMAND
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runlusearch.sh	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,21 @@
+#!/bin/bash
+if [ -z "${JDK7}" ]; then
+  echo "JDK7 is not defined."
+  exit 1;
+fi
+if [ -z "${MAXINE}" ]; then
+  echo "MAXINE is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${GRAAL}" ]; then
+  echo "GRAAL is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${DACAPO}" ]; then
+  echo "DACAPO is not defined. It must point to a Dacapo benchmark directory."
+  exit 1;
+fi
+COMMAND="${JDK7}/bin/java -client -d64 -graal -Xms1g -Xmx2g -esa -classpath ${DACAPO}/dacapo-9.12-bach.jar -XX:-GraalBailoutIsFatal -G:-QuietBailout $* Harness --preserve -n 5 lusearch"
+echo $COMMAND
+$COMMAND
+echo $COMMAND
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runscimark.sh	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,18 @@
+#!/bin/bash
+if [ -z "${JDK7}" ]; then
+  echo "JDK7 is not defined."
+  exit 1;
+fi
+if [ -z "${MAXINE}" ]; then
+  echo "MAXINE is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${GRAAL}" ]; then
+  echo "GRAAL is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${SCIMARK}" ]; then
+  echo "SCIMARK is not defined. It must point to a directory with the SciMark benchmark jar."
+  exit 1;
+fi
+${JDK7}/jre/bin/java -client -d64 -graal -Xms256m -Xmx512m -Xbootclasspath/a:${SCIMARK}/scimark2lib.jar $@ jnt.scimark2.commandline
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtests.sh	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,15 @@
+#!/bin/bash
+if [ -z "${JDK7}" ]; then
+  echo "JDK7 is not defined."
+  exit 1;
+fi
+if [ -z "${MAXINE}" ]; then
+  echo "MAXINE is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${GRAAL}" ]; then
+  echo "GRAAL is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+TESTDIR=${MAXINE}/com.oracle.max.vm/test
+${JDK7}/bin/java -client -d64 -graal -ea -esa -Xcomp -XX:+PrintCompilation -XX:CompileOnly=jtt $@ -Xbootclasspath/p:"${MAXINE}/com.oracle.max.vm/bin" -Xbootclasspath/p:"${MAXINE}/com.oracle.max.base/bin" $@ test.com.sun.max.vm.compiler.JavaTester -verbose=1 -gen-run-scheme=false -run-scheme-package=all ${TESTDIR}/jtt/bytecode ${TESTDIR}/jtt/except ${TESTDIR}/jtt/hotpath ${TESTDIR}/jtt/jdk ${TESTDIR}/jtt/lang ${TESTDIR}/jtt/loop ${TESTDIR}/jtt/micro ${TESTDIR}/jtt/optimize ${TESTDIR}/jtt/reflect ${TESTDIR}/jtt/threads ${TESTDIR}/jtt/hotspot
--- a/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -283,11 +283,12 @@
       jcc(Assembler::notZero, loop);
     }
   }
-
-  if (CURRENT_ENV->dtrace_alloc_probes()) {
-    assert(obj == rax, "must be");
-    call(RuntimeAddress(Runtime1::entry_for(Runtime1::dtrace_object_alloc_id)));
-  }
+  
+  // (tw) fix me
+//  if (CURRENT_ENV->dtrace_alloc_probes()) {
+//    assert(obj == rax, "must be");
+//    call(RuntimeAddress(Runtime1::entry_for(Runtime1::dtrace_object_alloc_id)));
+//  }
 
   verify_oop(obj);
 }
@@ -317,10 +318,11 @@
   const Register len_zero = len;
   initialize_body(obj, arr_size, header_size * BytesPerWord, len_zero);
 
-  if (CURRENT_ENV->dtrace_alloc_probes()) {
-    assert(obj == rax, "must be");
-    call(RuntimeAddress(Runtime1::entry_for(Runtime1::dtrace_object_alloc_id)));
-  }
+  // (tw) fix me
+//  if (CURRENT_ENV->dtrace_alloc_probes()) {
+//    assert(obj == rax, "must be");
+//    call(RuntimeAddress(Runtime1::entry_for(Runtime1::dtrace_object_alloc_id)));
+//  }
 
   verify_oop(obj);
 }
--- a/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -38,6 +38,7 @@
 #include "runtime/vframeArray.hpp"
 #include "vmreg_x86.inline.hpp"
 
+static void restore_live_registers(StubAssembler* sasm, bool restore_fpu_registers = true);
 
 // Implementation of StubAssembler
 
@@ -96,14 +97,11 @@
     if (oop_result2->is_valid()) {
       movptr(Address(thread, JavaThread::vm_result_2_offset()), NULL_WORD);
     }
-    if (frame_size() == no_frame_size) {
-      leave();
-      jump(RuntimeAddress(StubRoutines::forward_exception_entry()));
-    } else if (_stub_id == Runtime1::forward_exception_id) {
-      should_not_reach_here();
-    } else {
-      jump(RuntimeAddress(Runtime1::entry_for(Runtime1::forward_exception_id)));
-    }
+    // (tw) Deoptimize in case of an exception.
+    restore_live_registers(this, false);
+    movptr(Address(thread, Thread::pending_exception_offset()), NULL_WORD);
+    leave();
+    jump(RuntimeAddress(SharedRuntime::deopt_blob()->uncommon_trap()));
     bind(L);
   }
   // get oop results if there are any and reset the values in the thread
@@ -539,7 +537,7 @@
 }
 
 
-static void restore_live_registers(StubAssembler* sasm, bool restore_fpu_registers = true) {
+static void restore_live_registers(StubAssembler* sasm, bool restore_fpu_registers/* = true*/) {
   __ block_comment("restore_live_registers");
 
   restore_fpu(sasm, restore_fpu_registers);
@@ -593,30 +591,50 @@
 // has_argument: true if the exception needs an argument (passed on stack because registers must be preserved)
 
 OopMapSet* Runtime1::generate_exception_throw(StubAssembler* sasm, address target, bool has_argument) {
-  // preserve all registers
-  int num_rt_args = has_argument ? 2 : 1;
-  OopMap* oop_map = save_live_registers(sasm, num_rt_args);
+  OopMapSet* oop_maps = new OopMapSet();
+  if (UseGraal) {
+    // graal passes the argument in r10
+    OopMap* oop_map = save_live_registers(sasm, 1);
+
+    // now all registers are saved and can be used freely
+    // verify that no old value is used accidentally
+    __ invalidate_registers(true, true, true, true, true, true);
 
-  // now all registers are saved and can be used freely
-  // verify that no old value is used accidentally
-  __ invalidate_registers(true, true, true, true, true, true);
+    // registers used by this stub
+    const Register temp_reg = rbx;
 
-  // registers used by this stub
-  const Register temp_reg = rbx;
+    // load argument for exception that is passed as an argument into the stub
+    if (has_argument) {
+      __ movptr(c_rarg1, r10);
+    }
+    int call_offset = __ call_RT(noreg, noreg, target, has_argument ? 1 : 0);
 
-  // load argument for exception that is passed as an argument into the stub
-  if (has_argument) {
-#ifdef _LP64
-    __ movptr(c_rarg1, Address(rbp, 2*BytesPerWord));
-#else
-    __ movptr(temp_reg, Address(rbp, 2*BytesPerWord));
-    __ push(temp_reg);
-#endif // _LP64
+    oop_maps->add_gc_map(call_offset, oop_map);
+  } else {
+    // preserve all registers
+    int num_rt_args = has_argument ? 2 : 1;
+    OopMap* oop_map = save_live_registers(sasm, num_rt_args);
+
+    // now all registers are saved and can be used freely
+    // verify that no old value is used accidentally
+    __ invalidate_registers(true, true, true, true, true, true);
+
+    // registers used by this stub
+    const Register temp_reg = rbx;
+
+    // load argument for exception that is passed as an argument into the stub
+    if (has_argument) {
+  #ifdef _LP64
+      __ movptr(c_rarg1, Address(rbp, 2*BytesPerWord));
+  #else
+      __ movptr(temp_reg, Address(rbp, 2*BytesPerWord));
+      __ push(temp_reg);
+  #endif // _LP64
+    }
+    int call_offset = __ call_RT(noreg, noreg, target, num_rt_args - 1);
+
+    oop_maps->add_gc_map(call_offset, oop_map);
   }
-  int call_offset = __ call_RT(noreg, noreg, target, num_rt_args - 1);
-
-  OopMapSet* oop_maps = new OopMapSet();
-  oop_maps->add_gc_map(call_offset, oop_map);
 
   __ stop("should not reach here");
 
@@ -754,6 +772,74 @@
   return oop_maps;
 }
 
+void Runtime1::graal_generate_handle_exception(StubAssembler *sasm, OopMapSet* oop_maps, OopMap* oop_map) {
+  NOT_LP64(fatal("64 bit only"));
+  // incoming parameters
+  const Register exception_oop = j_rarg0;
+  // other registers used in this stub
+  const Register exception_pc = j_rarg1;
+  const Register thread = r15_thread;
+
+  __ block_comment("graal_generate_handle_exception");
+
+  // verify that rax, contains a valid exception
+  __ verify_not_null_oop(exception_oop);
+
+#ifdef ASSERT
+  // check that fields in JavaThread for exception oop and issuing pc are
+  // empty before writing to them
+  Label oop_empty;
+  __ cmpptr(Address(thread, JavaThread::exception_oop_offset()), (int32_t) NULL_WORD);
+  __ jcc(Assembler::equal, oop_empty);
+  __ stop("exception oop already set");
+  __ bind(oop_empty);
+
+  Label pc_empty;
+  __ cmpptr(Address(thread, JavaThread::exception_pc_offset()), 0);
+  __ jcc(Assembler::equal, pc_empty);
+  __ stop("exception pc already set");
+  __ bind(pc_empty);
+#endif
+
+  // save exception oop and issuing pc into JavaThread
+  // (exception handler will load it from here)
+  __ movptr(Address(thread, JavaThread::exception_oop_offset()), exception_oop);
+  __ movptr(exception_pc, Address(rbp, 1*BytesPerWord));
+  __ movptr(Address(thread, JavaThread::exception_pc_offset()), exception_pc);
+
+  // compute the exception handler.
+  // the exception oop and the throwing pc are read from the fields in JavaThread
+  int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, exception_handler_for_pc));
+  oop_maps->add_gc_map(call_offset, oop_map);
+
+  // rax,: handler address
+  //      will be the deopt blob if nmethod was deoptimized while we looked up
+  //      handler regardless of whether handler existed in the nmethod.
+
+  // only rax, is valid at this time, all other registers have been destroyed by the runtime call
+  __ invalidate_registers(false, true, true, true, true, true);
+
+#ifdef ASSERT
+  // Do we have an exception handler in the nmethod?
+  Label done;
+  __ testptr(rax, rax);
+  __ jcc(Assembler::notZero, done);
+  __ stop("no handler found");
+  __ bind(done);
+#endif
+
+  // exception handler found
+  // patch the return address -> the stub will directly return to the exception handler
+  __ movptr(Address(rbp, 1*BytesPerWord), rax);
+
+  // restore registers
+  restore_live_registers(sasm, false);
+
+  // return to exception handler
+  __ leave();
+  __ ret(0);
+}
+
 
 void Runtime1::generate_unwind_exception(StubAssembler *sasm) {
   // incoming parameters
@@ -961,6 +1047,12 @@
   return oop_maps;
 }
 
+JRT_ENTRY(void, graal_create_null_exception(JavaThread* thread))
+  thread->set_vm_result(Exceptions::new_exception(thread, vmSymbols::java_lang_NullPointerException(), NULL)());
+JRT_END
+
+
+
 
 OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
 
@@ -1254,8 +1346,8 @@
         // will be place in C abi locations
 
 #ifdef _LP64
-        __ verify_oop(c_rarg0);
-        __ mov(rax, c_rarg0);
+        __ verify_oop((UseGraal) ? j_rarg0 : c_rarg0);
+        __ mov(rax, (UseGraal) ? j_rarg0 : c_rarg0);
 #else
         // The object is passed on the stack and we haven't pushed a
         // frame yet so it's one work away from top of stack.
@@ -1326,7 +1418,8 @@
       break;
 
     case unwind_exception_id:
-      { __ set_info("unwind_exception", dont_gc_arguments);
+      {
+        __ set_info("unwind_exception", dont_gc_arguments);
         // note: no stubframe since we are about to leave the current
         //       activation and we are calling a leaf VM function only.
         generate_unwind_exception(sasm);
@@ -1385,10 +1478,17 @@
         __ movptr(rsi, Address(rsp, (klass_off) * VMRegImpl::stack_slot_size)); // subclass
         __ movptr(rax, Address(rsp, (sup_k_off) * VMRegImpl::stack_slot_size)); // superclass
 
+        Label success;
         Label miss;
+        if (UseGraal) {
+          // TODO this should really be within the XirSnippets
+          __ check_klass_subtype_fast_path(rsi, rax, rcx, &success, &miss, NULL);
+        };
+
         __ check_klass_subtype_slow_path(rsi, rax, rcx, rdi, NULL, &miss);
 
         // fallthrough on success:
+        __ bind(success);
         __ movptr(Address(rsp, (result_off) * VMRegImpl::stack_slot_size), 1); // result
         __ pop(rax);
         __ pop(rcx);
@@ -1786,6 +1886,181 @@
       break;
 #endif // !SERIALGC
 
+    case graal_unwind_exception_call_id: {
+      // remove the frame from the stack
+      __ movptr(rsp, rbp);
+      __ pop(rbp);
+      // exception_oop is passed using ordinary java calling conventions
+      __ movptr(rax, j_rarg0);
+
+      Label nonNullExceptionOop;
+      __ testptr(rax, rax);
+      __ jcc(Assembler::notZero, nonNullExceptionOop);
+      {
+        __ enter();
+        oop_maps = new OopMapSet();
+        OopMap* oop_map = save_live_registers(sasm, 0);
+        int call_offset = __ call_RT(rax, noreg, (address)graal_create_null_exception, 0);
+        oop_maps->add_gc_map(call_offset, oop_map);
+        __ leave();
+      }
+      __ bind(nonNullExceptionOop);
+
+      __ set_info("unwind_exception", dont_gc_arguments);
+      // note: no stubframe since we are about to leave the current
+      //       activation and we are calling a leaf VM function only.
+      generate_unwind_exception(sasm);
+      __ should_not_reach_here();
+      break;
+    }
+
+    case graal_handle_exception_id: {
+      StubFrame f(sasm, "graal_handle_exception", dont_gc_arguments);
+      oop_maps = new OopMapSet();
+      OopMap* oop_map = save_live_registers(sasm, 1, false);
+      graal_generate_handle_exception(sasm, oop_maps, oop_map);
+      break;
+    }
+
+    case graal_slow_subtype_check_id: {
+      Label success;
+      Label miss;
+
+      // TODO this should really be within the XirSnippets
+      __ check_klass_subtype_fast_path(j_rarg0, j_rarg1, j_rarg2, &success, &miss, NULL);
+      __ check_klass_subtype_slow_path(j_rarg0, j_rarg1, j_rarg2, j_rarg3, NULL, &miss);
+
+      // fallthrough on success:
+      __ bind(success);
+      __ movptr(rax, 1);
+      __ ret(0);
+
+      __ bind(miss);
+      __ movptr(rax, NULL_WORD);
+      __ ret(0);
+      break;
+    }
+
+    case graal_verify_pointer_id: {
+      __ verify_oop(r13, "graal verify pointer");
+      __ ret(0);
+      break;
+    }
+
+    case graal_arithmetic_frem_id: {
+      __ subptr(rsp, 8);
+      __ movflt(Address(rsp, 0), xmm1);
+      __ fld_s(Address(rsp, 0));
+      __ movflt(Address(rsp, 0), xmm0);
+      __ fld_s(Address(rsp, 0));
+      Label L;
+      __ bind(L);
+      __ fprem();
+      __ fwait();
+      __ fnstsw_ax();
+      __ testl(rax, 0x400);
+      __ jcc(Assembler::notZero, L);
+      __ fxch(1);
+      __ fpop();
+      __ fstp_s(Address(rsp, 0));
+      __ movflt(xmm0, Address(rsp, 0));
+      __ addptr(rsp, 8);
+      __ ret(0);
+      break;
+    }
+    case graal_arithmetic_drem_id: {
+      __ subptr(rsp, 8);
+      __ movdbl(Address(rsp, 0), xmm1);
+      __ fld_d(Address(rsp, 0));
+      __ movdbl(Address(rsp, 0), xmm0);
+      __ fld_d(Address(rsp, 0));
+      Label L;
+      __ bind(L);
+      __ fprem();
+      __ fwait();
+      __ fnstsw_ax();
+      __ testl(rax, 0x400);
+      __ jcc(Assembler::notZero, L);
+      __ fxch(1);
+      __ fpop();
+      __ fstp_d(Address(rsp, 0));
+      __ movdbl(xmm0, Address(rsp, 0));
+      __ addptr(rsp, 8);
+      __ ret(0);
+      break;
+    }
+    case graal_monitorenter_id: {
+      Label slow_case;
+
+      Register obj = j_rarg0;
+      Register lock = j_rarg1;
+
+      Register scratch1 = rax;
+      Register scratch2 = rbx;
+      assert_different_registers(obj, lock, scratch1, scratch2);
+
+      // copied from LIR_Assembler::emit_lock
+      if (UseFastLocking) {
+        assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header");
+        __ lock_object(scratch1, obj, lock, scratch2, slow_case);
+      __ ret(0);
+      }
+
+      __ bind(slow_case);
+      {
+        StubFrame f(sasm, "graal_monitorenter", dont_gc_arguments);
+        OopMap* map = save_live_registers(sasm, 1, save_fpu_registers);
+
+        // Called with store_parameter and not C abi
+        int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, monitorenter), obj, lock);
+
+        oop_maps = new OopMapSet();
+        oop_maps->add_gc_map(call_offset, map);
+        restore_live_registers(sasm, save_fpu_registers);
+      }
+      __ ret(0);
+      break;
+    }
+    case graal_monitorexit_id: {
+      Label slow_case;
+
+      Register obj = j_rarg0;
+      Register lock = j_rarg1;
+
+      // needed in rax later on...
+      Register lock2 = rax;
+      __ mov(lock2, lock);
+      Register scratch1 = rbx;
+      assert_different_registers(obj, lock, scratch1, lock2);
+
+      // copied from LIR_Assembler::emit_lock
+      if (UseFastLocking) {
+        assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header");
+        __ unlock_object(scratch1, obj, lock2, slow_case);
+      __ ret(0);
+      }
+
+      __ bind(slow_case);
+      {
+        StubFrame f(sasm, "graal_monitorexit", dont_gc_arguments);
+        OopMap* map = save_live_registers(sasm, 2, save_fpu_registers);
+
+        // note: really a leaf routine but must setup last java sp
+        //       => use call_RT for now (speed can be improved by
+        //       doing last java sp setup manually)
+        int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, monitorexit), lock);
+
+        oop_maps = new OopMapSet();
+        oop_maps->add_gc_map(call_offset, map);
+        restore_live_registers(sasm, save_fpu_registers);
+      }
+      __ ret(0);
+      break;
+    }
+
+
+
+
     default:
       { StubFrame f(sasm, "unimplemented entry", dont_gc_arguments);
         __ movptr(rax, (int)id);
--- a/src/cpu/x86/vm/c1_globals_x86.hpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/cpu/x86/vm/c1_globals_x86.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -37,10 +37,10 @@
 define_pd_global(bool, ResizeTLAB,                   true );
 define_pd_global(bool, InlineIntrinsics,             true );
 define_pd_global(bool, PreferInterpreterNativeStubs, false);
-define_pd_global(bool, ProfileTraps,                 false);
+define_pd_global(bool, ProfileTraps,                 true );
 define_pd_global(bool, UseOnStackReplacement,        true );
 define_pd_global(bool, TieredCompilation,            false);
-define_pd_global(intx, CompileThreshold,             1500 );
+define_pd_global(intx, CompileThreshold,             5000 );   // changed for GRAAL
 define_pd_global(intx, BackEdgeThreshold,            100000);
 
 define_pd_global(intx, OnStackReplacePercentage,     933  );
@@ -48,7 +48,7 @@
 define_pd_global(intx, NewSizeThreadIncrease,        4*K  );
 define_pd_global(intx, InitialCodeCacheSize,         160*K);
 define_pd_global(intx, ReservedCodeCacheSize,        32*M );
-define_pd_global(bool, ProfileInterpreter,           false);
+define_pd_global(bool, ProfileInterpreter,           true );    // changed for GRAAL
 define_pd_global(intx, CodeCacheExpansionSize,       32*K );
 define_pd_global(uintx,CodeCacheMinBlockLength,      1);
 define_pd_global(uintx,PermSize,                     12*M );
@@ -57,7 +57,7 @@
 define_pd_global(uint64_t,MaxRAM,                    1ULL*G);
 define_pd_global(bool, CICompileOSR,                 true );
 #endif // !TIERED
-define_pd_global(bool, UseTypeProfile,               false);
+define_pd_global(bool, UseTypeProfile,               true );    // changed for GRAAL
 define_pd_global(bool, RoundFPResults,               true );
 
 define_pd_global(bool, LIRFillDelaySlots,            false);
--- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -126,6 +126,7 @@
   static int rax_offset_in_bytes(void)    { return BytesPerInt * rax_off; }
   static int rdx_offset_in_bytes(void)    { return BytesPerInt * rdx_off; }
   static int rbx_offset_in_bytes(void)    { return BytesPerInt * rbx_off; }
+  static int r10_offset_in_bytes(void)    { return BytesPerInt * r10_off; }
   static int xmm0_offset_in_bytes(void)   { return BytesPerInt * xmm0_off; }
   static int return_offset_in_bytes(void) { return BytesPerInt * return_off; }
 
@@ -2636,6 +2637,51 @@
   __ bind(no_pending_exception);
 #endif
 
+  // (tw) Start of graal uncommon trap code.
+  __ jmp(cont);
+
+  int jmp_uncommon_trap_offset = __ pc() - start;
+  __ pushptr(Address(r15_thread, in_bytes(JavaThread::ScratchA_offset())));
+  __ movptr(rscratch1, 0);
+
+  int uncommon_trap_offset = __ pc() - start;
+
+  // Warning: Duplicate code
+
+  // Save everything in sight.
+  map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words);
+
+  // Normal deoptimization
+
+
+  // fetch_unroll_info needs to call last_java_frame()
+  __ set_last_Java_frame(noreg, noreg, NULL);
+
+
+  //  __ movl(c_rarg1, (int32_t)Deoptimization::Unpack_reexecute);
+  //  __ movl(r14, c_rarg1); // save into r14 for later call to unpack_frames
+
+  assert(r10 == rscratch1, "scratch register should be r10");
+  __ movptr(c_rarg1, Address(rsp, RegisterSaver::r10_offset_in_bytes()));
+  __ orq(c_rarg1, ~(int32_t)Deoptimization::make_trap_request(Deoptimization::Reason_unreached, Deoptimization::Action_none));
+  __ notq(c_rarg1);
+  __ movl(r14, (int32_t)Deoptimization::Unpack_reexecute);
+  __ mov(c_rarg0, r15_thread);
+  __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap)));
+
+  // Need to have an oopmap that tells fetch_unroll_info where to
+  // find any register it might need.
+
+  oop_maps->add_gc_map( __ pc()-start, map->deep_copy());
+
+  __ reset_last_Java_frame(false, false);
+
+  Label after_fetch_unroll_info_call;
+  __ jmp(after_fetch_unroll_info_call);
+
+
+  // (tw) End of graal uncommon trap code.
+
   __ bind(cont);
 
   // Call C code.  Need thread and this frame, but NOT official VM entry
@@ -2665,6 +2711,8 @@
 
   __ reset_last_Java_frame(false, false);
 
+  __ bind(after_fetch_unroll_info_call);
+
   // Load UnrollBlock* into rdi
   __ mov(rdi, rax);
 
@@ -2691,7 +2739,7 @@
   // or captured in the vframeArray.
   RegisterSaver::restore_result_registers(masm);
 
-  // All of the register save area has been popped of the stack. Only the
+  // All of the register save area has been poppeset_jmp_uncommon_trap_offsetd of the stack. Only the
   // return address remains.
 
   // Pop all the frames we must move/replace.
@@ -2826,6 +2874,8 @@
 
   _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);
+  _deopt_blob->set_uncommon_trap_offset(uncommon_trap_offset);
+  _deopt_blob->set_jmp_uncommon_trap_offset(jmp_uncommon_trap_offset);
 }
 
 #ifdef COMPILER2
--- a/src/os/linux/vm/os_linux.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/os/linux/vm/os_linux.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -3611,7 +3611,14 @@
 
 void signalHandler(int sig, siginfo_t* info, void* uc) {
   assert(info != NULL && uc != NULL, "it must be old kernel");
+  ResourceMark rm;
+  if (TraceSignals) {
+    tty->print_cr(err_msg("signal received: code=%d errno=%d signo=%d thread=%s address=%x", info->si_code, info->si_errno, info->si_signo, Thread::current()->name(), info->si_addr));
+  }
   JVM_handle_linux_signal(sig, info, uc, true);
+  if (TraceSignals) {
+    tty->print_cr("signal handled");
+  }
 }
 
 
--- a/src/os/windows/vm/os_windows.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/os/windows/vm/os_windows.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -408,7 +408,6 @@
     }
   }
 
-
   if (UseVectoredExceptions) {
     // If we are using vectored exception we don't need to set a SEH
     thread->run();
--- a/src/os_cpu/linux_x86/vm/os_linux_x86.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/os_cpu/linux_x86/vm/os_linux_x86.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -289,6 +289,17 @@
     }
 #endif // AMD64
 
+    if (TraceSignals) {
+    CodeBlob* cb = CodeCache::find_blob(pc);
+      if (cb != NULL && cb->is_nmethod()) {
+        nmethod* nm = (nmethod*)cb;
+        int rel = pc - nm->code_begin();
+        tty->print_cr(err_msg("Implicit exception at %d of method %s", rel, nm->method()->name()->as_C_string()));
+      } else {
+        tty->print_cr("No code blob found for %x", pc);
+      }
+    }
+
     // Handle ALL stack overflow variations here
     if (sig == SIGSEGV) {
       address addr = (address) info->si_addr;
@@ -302,6 +313,7 @@
           if (thread->thread_state() == _thread_in_Java) {
             // Throw a stack overflow exception.  Guard pages will be reenabled
             // while unwinding the stack.
+            if (WizardMode) tty->print("implicit: %08x%08x\n", ((long)pc) >> 32, pc);
             stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW);
           } else {
             // Thread was in the vm or native code.  Return and try to finish.
@@ -387,8 +399,15 @@
 #endif // AMD64
       } else if (sig == SIGSEGV &&
                !MacroAssembler::needs_explicit_null_check((intptr_t)info->si_addr)) {
+          if (TraceSignals) {
+            tty->print_cr("Implicit exception continuation");
+          }
           // Determination of interpreter/vtable stub/compiled code null exception
           stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
+      } else if (sig == SIGSEGV) {
+        if (TraceSignals) {
+          tty->print_cr("would have needed explicit null check %d", (intptr_t)info->si_addr);
+        }
       }
     } else if (thread->thread_state() == _thread_in_vm &&
                sig == SIGBUS && /* info->si_code == BUS_OBJERR && */
--- a/src/share/tools/IdealGraphVisualizer/BatikSVGProxy/nbproject/build-impl.xml	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/BatikSVGProxy/nbproject/build-impl.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -4,6 +4,13 @@
 ***         EDIT ../build.xml INSTEAD         ***
 -->
 <project name="com.sun.hotspot.igv.svg-impl" basedir="..">
+    <fail message="Please build using Ant 1.7.1 or higher.">
+        <condition>
+            <not>
+                <antversion atleast="1.7.1"/>
+            </not>
+        </condition>
+    </fail>
     <property file="nbproject/private/suite-private.properties"/>
     <property file="nbproject/suite.properties"/>
     <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
@@ -16,13 +23,21 @@
             <property name="@{name}" value="${@{value}}"/>
         </sequential>
     </macrodef>
+    <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="property"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{property}" value="@{value}"/>
+        </sequential>
+    </macrodef>
     <property file="${user.properties.file}"/>
     <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
-    <nbmproject2:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
-    <fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'">
+    <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
         <condition>
             <not>
-                <available file="${harness.dir}" type="dir"/>
+                <contains string="${cluster.path.evaluated}" substring="platform"/>
             </not>
         </condition>
     </fail>
--- a/src/share/tools/IdealGraphVisualizer/BatikSVGProxy/nbproject/genfiles.properties	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/BatikSVGProxy/nbproject/genfiles.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -1,8 +1,5 @@
-build.xml.data.CRC32=ebcf0422
-build.xml.script.CRC32=d7a2678d
-build.xml.stylesheet.CRC32=79c3b980
 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
 # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
 nbproject/build-impl.xml.data.CRC32=ebcf0422
-nbproject/build-impl.xml.script.CRC32=57997f94
-nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
+nbproject/build-impl.xml.script.CRC32=42ef3ff6
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.45.1
--- a/src/share/tools/IdealGraphVisualizer/BatikSVGProxy/src/com/sun/hotspot/igv/svg/BatikSVG.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/BatikSVGProxy/src/com/sun/hotspot/igv/svg/BatikSVG.java	Wed Jul 27 17:32:44 2011 -0700
@@ -31,34 +31,42 @@
 import org.w3c.dom.DOMImplementation;
 
 /**
- *
+ * Utility class
  * @author Thomas Wuerthinger
  */
 public class BatikSVG {
 
+    private BatikSVG() {
+    }
+
     private static Constructor SVGGraphics2DConstructor;
-    private static Method Method_stream;
-    private static Method Method_createDefault;
-    private static Method Method_getDOMImplementation;
-    private static Method Method_setEmbeddedFontsOn;
+    private static Method streamMethod;
+    private static Method createDefaultMethod;
+    private static Method getDOMImplementationMethod;
+    private static Method setEmbeddedFontsOnMethod;
+    private static Class<?> classSVGGraphics2D;
 
+    /**
+     * Creates a graphics object that allows to be exported to SVG data using the {@link #printToStream(Graphics2D, Writer, boolean) printToStream} method.
+     * @return the newly created Graphics2D object or null if the library does not exist
+     */
     public static Graphics2D createGraphicsObject() {
         try {
             if (SVGGraphics2DConstructor == null) {
                 ClassLoader cl = BatikSVG.class.getClassLoader();
-                Class Class_GenericDOMImplementation = cl.loadClass("org.apache.batik.dom.GenericDOMImplementation");
-                Class Class_SVGGeneratorContext = cl.loadClass("org.apache.batik.svggen.SVGGeneratorContext");
-                Class Class_SVGGraphics2D = cl.loadClass("org.apache.batik.svggen.SVGGraphics2D");
-                Method_getDOMImplementation = Class_GenericDOMImplementation.getDeclaredMethod("getDOMImplementation", new Class[0]);
-                Method_createDefault = Class_SVGGeneratorContext.getDeclaredMethod("createDefault", new Class[]{org.w3c.dom.Document.class});
-                Method_setEmbeddedFontsOn = Class_SVGGeneratorContext.getDeclaredMethod("setEmbeddedFontsOn", new Class[]{boolean.class});
-                Method_stream = Class_SVGGraphics2D.getDeclaredMethod("stream", Writer.class, boolean.class);
-                SVGGraphics2DConstructor = Class_SVGGraphics2D.getConstructor(Class_SVGGeneratorContext, boolean.class);
+                Class<?> classGenericDOMImplementation = cl.loadClass("org.apache.batik.dom.GenericDOMImplementation");
+                Class<?> classSVGGeneratorContext = cl.loadClass("org.apache.batik.svggen.SVGGeneratorContext");
+                classSVGGraphics2D = cl.loadClass("org.apache.batik.svggen.SVGGraphics2D");
+                getDOMImplementationMethod = classGenericDOMImplementation.getDeclaredMethod("getDOMImplementation", new Class[0]);
+                createDefaultMethod = classSVGGeneratorContext.getDeclaredMethod("createDefault", new Class[]{org.w3c.dom.Document.class});
+                setEmbeddedFontsOnMethod = classSVGGeneratorContext.getDeclaredMethod("setEmbeddedFontsOn", new Class[]{boolean.class});
+                streamMethod = classSVGGraphics2D.getDeclaredMethod("stream", Writer.class, boolean.class);
+                SVGGraphics2DConstructor = classSVGGraphics2D.getConstructor(classSVGGeneratorContext, boolean.class);
             }
-            DOMImplementation dom = (DOMImplementation) Method_getDOMImplementation.invoke(null);
+            DOMImplementation dom = (DOMImplementation) getDOMImplementationMethod.invoke(null);
             org.w3c.dom.Document document = dom.createDocument("http://www.w3.org/2000/svg", "svg", null);
-            Object ctx = Method_createDefault.invoke(null, document);
-            Method_setEmbeddedFontsOn.invoke(ctx, true);
+            Object ctx = createDefaultMethod.invoke(null, document);
+            setEmbeddedFontsOnMethod.invoke(ctx, true);
             Graphics2D svgGenerator = (Graphics2D) SVGGraphics2DConstructor.newInstance(ctx, true);
             return svgGenerator;
         } catch (ClassNotFoundException e) {
@@ -74,9 +82,17 @@
         }
     }
 
+    /**
+     * Serializes a graphics object to a stream in SVG format.
+     * @param svgGenerator the graphics object. Only graphics objects created by the {@link #createGraphicsObject() createGraphicsObject} method are valid.
+     * @param stream the stream to which the data is written
+     * @param useCSS whether to use CSS styles in the SVG output
+     */
     public static void printToStream(Graphics2D svgGenerator, Writer stream, boolean useCSS) {
+        assert classSVGGraphics2D != null;
+        assert classSVGGraphics2D.isInstance(svgGenerator);
         try {
-            Method_stream.invoke(svgGenerator, stream, useCSS);
+            streamMethod.invoke(svgGenerator, stream, useCSS);
         } catch (IllegalAccessException e) {
             assert false;
         } catch (InvocationTargetException e) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/BatikSVGProxy/src/com/sun/hotspot/igv/svg/package-info.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+/**
+ * This package is used to proxy the SVG export functionality of the BatikSVG library. Reflection is used such that the
+ * library is optional and need not be present at build time.
+ */
+package com.sun.hotspot.igv.svg;
+
--- a/src/share/tools/IdealGraphVisualizer/Bytecodes/manifest.mf	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Bytecodes/manifest.mf	Wed Jul 27 17:32:44 2011 -0700
@@ -1,6 +1,6 @@
-Manifest-Version: 1.0
-OpenIDE-Module: com.sun.hotspot.igv.bytecodes
-OpenIDE-Module-Layer: com/sun/hotspot/igv/bytecodes/layer.xml
-OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/bytecodes/Bundle.properties
-OpenIDE-Module-Specification-Version: 1.0
-
+Manifest-Version: 1.0
+OpenIDE-Module: com.sun.hotspot.igv.bytecodes
+OpenIDE-Module-Layer: com/sun/hotspot/igv/bytecodes/layer.xml
+OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/bytecodes/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
--- a/src/share/tools/IdealGraphVisualizer/Bytecodes/nbproject/project.xml	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Bytecodes/nbproject/project.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -15,12 +15,28 @@
                     </run-dependency>
                 </dependency>
                 <dependency>
+                    <code-name-base>com.sun.hotspot.igv.graph</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.util</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
                     <code-name-base>org.jdesktop.layout</code-name-base>
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>1</release-version>
-                        <specification-version>1.4</specification-version>
+                        <specification-version>1.16.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -28,7 +44,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.11</specification-version>
+                        <specification-version>6.34.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -36,7 +52,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.2.0.1</specification-version>
+                        <specification-version>7.20.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -44,7 +60,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.9.0.1</specification-version>
+                        <specification-version>8.14.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.lookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.6.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -52,7 +76,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.16</specification-version>
+                        <specification-version>6.39.1</specification-version>
                     </run-dependency>
                 </dependency>
             </module-dependencies>
--- a/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/Bundle.properties	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/Bundle.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -1,5 +1,5 @@
 CTL_BytecodeViewAction=Open BytecodeView Window
-CTL_BytecodeViewTopComponent=BytecodeView Window
+CTL_BytecodeViewTopComponent=Bytecode
 CTL_SelectBytecodesAction=Select nodes
-HINT_BytecodeViewTopComponent=This is a BytecodeView window
+HINT_BytecodeViewTopComponent=Shows the bytecode associated with the displayed graph.
 OpenIDE-Module-Name=Bytecodes
--- a/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeNode.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeNode.java	Wed Jul 27 17:32:44 2011 -0700
@@ -29,14 +29,14 @@
 import com.sun.hotspot.igv.data.Properties;
 import com.sun.hotspot.igv.data.Properties.StringPropertyMatcher;
 import java.awt.Image;
-import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
 import javax.swing.Action;
 import org.openide.nodes.AbstractNode;
 import org.openide.nodes.Children;
 import org.openide.nodes.Node;
-import org.openide.util.Utilities;
+import org.openide.util.ImageUtilities;
 
 /**
  *
@@ -58,7 +58,7 @@
         StringPropertyMatcher matcher = new StringPropertyMatcher("bci", bciValue);
         List<InputNode> nodeList = selector.selectMultiple(matcher);
         if (nodeList.size() > 0) {
-            nodes = new HashSet<InputNode>();
+            nodes = new LinkedHashSet<InputNode>();
             for (InputNode n : nodeList) {
                 nodes.add(n);
             }
@@ -69,9 +69,9 @@
     @Override
     public Image getIcon(int i) {
         if (nodes != null) {
-            return Utilities.loadImage("com/sun/hotspot/igv/bytecodes/images/link.gif");
+            return ImageUtilities.loadImage("com/sun/hotspot/igv/bytecodes/images/link.png");
         } else {
-            return Utilities.loadImage("com/sun/hotspot/igv/bytecodes/images/bytecode.gif");
+            return ImageUtilities.loadImage("com/sun/hotspot/igv/bytecodes/images/bytecode.png");
         }
     }
 
@@ -91,6 +91,7 @@
     }
 
     @Override
+    @SuppressWarnings("unchecked")
     public <T extends Node.Cookie> T getCookie(Class<T> aClass) {
         if (aClass == SelectBytecodesCookie.class && nodes != null) {
             return (T) (new SelectBytecodesCookie(nodes));
--- a/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponent.form	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponent.form	Wed Jul 27 17:32:44 2011 -0700
@@ -3,6 +3,8 @@
 <Form version="1.3" maxVersion="1.3" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
   <AuxValues>
     <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
     <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
     <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
     <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="2"/>
--- a/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponent.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponent.java	Wed Jul 27 17:32:44 2011 -0700
@@ -26,6 +26,7 @@
 import com.sun.hotspot.igv.data.Group;
 import com.sun.hotspot.igv.data.InputGraph;
 import com.sun.hotspot.igv.data.services.InputGraphProvider;
+import com.sun.hotspot.igv.util.LookupHistory;
 import java.awt.BorderLayout;
 import java.io.Serializable;
 import javax.swing.SwingUtilities;
@@ -91,6 +92,7 @@
     }// </editor-fold>//GEN-END:initComponents
     // Variables declaration - do not modify//GEN-BEGIN:variables
     // End of variables declaration//GEN-END:variables
+
     /**
      * Gets default instance. Do not use directly: reserved for *.settings files only,
      * i.e. deserialization routines; otherwise you could get a non-deserialized instance.
@@ -126,7 +128,7 @@
 
     @Override
     public void componentOpened() {
-        Lookup.Template tpl = new Lookup.Template(Object.class);
+        Lookup.Template<InputGraphProvider> tpl = new Lookup.Template<InputGraphProvider>(InputGraphProvider.class);
         result = Utilities.actionsGlobalContext().lookup(tpl);
         result.addLookupListener(this);
     }
@@ -151,17 +153,35 @@
         return manager;
     }
 
+    @Override
+    public void requestActive() {
+        super.requestActive();
+        this.treeView.requestFocus();
+    }
+
+    @Override
+    public boolean requestFocus(boolean temporary) {
+        this.treeView.requestFocus();
+        return super.requestFocus(temporary);
+    }
+
+    @Override
+    protected boolean requestFocusInWindow(boolean temporary) {
+        this.treeView.requestFocus();
+        return super.requestFocusInWindow(temporary);
+    }
+
     public void resultChanged(LookupEvent lookupEvent) {
-        final InputGraphProvider p = Lookup.getDefault().lookup(InputGraphProvider.class);
+        final InputGraphProvider p = LookupHistory.getLast(InputGraphProvider.class);//)Utilities.actionsGlobalContext().lookup(InputGraphProvider.class);
         if (p != null) {
             SwingUtilities.invokeLater(new Runnable() {
                 public void run() {
-            InputGraph graph = p.getGraph();
-            if (graph != null) {
-                Group g = graph.getGroup();
-                rootNode.update(graph, g.getMethod());
-            }
-        }
+                    InputGraph graph = p.getGraph();
+                    if (graph != null) {
+                        Group g = graph.getGroup();
+                        rootNode.update(graph, g.getMethod());
+                    }
+                }
             });
         }
     }
--- a/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/MethodNode.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/MethodNode.java	Wed Jul 27 17:32:44 2011 -0700
@@ -30,7 +30,7 @@
 import org.openide.nodes.AbstractNode;
 import org.openide.nodes.Children;
 import org.openide.nodes.Node;
-import org.openide.util.Utilities;
+import org.openide.util.ImageUtilities;
 
 /**
  *
@@ -38,7 +38,7 @@
  */
 public class MethodNode extends AbstractNode {
 
-    private static class MethodNodeChildren extends Children.Keys {
+    private static class MethodNodeChildren extends Children.Keys<InputBytecode> {
 
         private InputMethod method;
         private InputGraph graph;
@@ -50,9 +50,7 @@
             this.graph = graph;
         }
 
-        protected Node[] createNodes(Object object) {
-            assert object instanceof InputBytecode;
-            InputBytecode bc = (InputBytecode) object;
+        protected Node[] createNodes(InputBytecode bc) {
             if (bc.getInlined() == null) {
                 return new Node[]{new BytecodeNode(bc, graph, bciString)};
             } else {
@@ -84,7 +82,7 @@
 
     @Override
     public Image getIcon(int i) {
-        return Utilities.loadImage("com/sun/hotspot/igv/bytecodes/images/method.gif");
+        return ImageUtilities.loadImage("com/sun/hotspot/igv/bytecodes/images/method.png");
     }
 
     @Override
--- a/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/SelectBytecodesAction.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/SelectBytecodesAction.java	Wed Jul 27 17:32:44 2011 -0700
@@ -24,10 +24,11 @@
 package com.sun.hotspot.igv.bytecodes;
 
 import com.sun.hotspot.igv.data.services.InputGraphProvider;
+import com.sun.hotspot.igv.util.LookupHistory;
 import org.openide.nodes.Node;
 import org.openide.util.HelpCtx;
-import org.openide.util.Lookup;
 import org.openide.util.NbBundle;
+import org.openide.util.Utilities;
 import org.openide.util.actions.CookieAction;
 
 /**
@@ -38,7 +39,7 @@
 
     protected void performAction(Node[] activatedNodes) {
         SelectBytecodesCookie c = activatedNodes[0].getCookie(SelectBytecodesCookie.class);
-        InputGraphProvider p = Lookup.getDefault().lookup(InputGraphProvider.class);
+        InputGraphProvider p = LookupHistory.getLast(InputGraphProvider.class);//Utilities.actionsGlobalContext().lookup(InputGraphProvider.class);
         if (p != null) {
             p.setSelectedNodes(c.getNodes());
         }
@@ -73,3 +74,4 @@
         return false;
     }
 }
+
Binary file src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/images/bytecode.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/images/bytecode.png has changed
Binary file src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/images/link.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/images/link.png has changed
Binary file src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/images/method.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/images/method.png has changed
--- a/src/share/tools/IdealGraphVisualizer/ControlFlow/manifest.mf	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/manifest.mf	Wed Jul 27 17:32:44 2011 -0700
@@ -1,6 +1,6 @@
-Manifest-Version: 1.0
-OpenIDE-Module: com.sun.hotspot.igv.controlflow
-OpenIDE-Module-Layer: com/sun/hotspot/igv/controlflow/layer.xml
-OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/controlflow/Bundle.properties
-OpenIDE-Module-Specification-Version: 1.0
-
+Manifest-Version: 1.0
+OpenIDE-Module: com.sun.hotspot.igv.controlflow
+OpenIDE-Module-Layer: com/sun/hotspot/igv/controlflow/layer.xml
+OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/controlflow/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
--- a/src/share/tools/IdealGraphVisualizer/ControlFlow/nbproject/project.xml	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/nbproject/project.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -31,12 +31,20 @@
                     </run-dependency>
                 </dependency>
                 <dependency>
+                    <code-name-base>com.sun.hotspot.igv.util</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
                     <code-name-base>org.jdesktop.layout</code-name-base>
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>1</release-version>
-                        <specification-version>1.4</specification-version>
+                        <specification-version>1.16.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -52,7 +60,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.9.0.1</specification-version>
+                        <specification-version>8.14.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.lookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.6.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
--- a/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/BlockConnectionWidget.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/BlockConnectionWidget.java	Wed Jul 27 17:32:44 2011 -0700
@@ -26,7 +26,9 @@
 import com.sun.hotspot.igv.data.InputBlockEdge;
 import com.sun.hotspot.igv.layout.Link;
 import com.sun.hotspot.igv.layout.Port;
+import java.awt.BasicStroke;
 import java.awt.Point;
+import java.awt.Stroke;
 import java.util.ArrayList;
 import java.util.List;
 import org.netbeans.api.visual.widget.ConnectionWidget;
@@ -37,12 +39,19 @@
  */
 public class BlockConnectionWidget extends ConnectionWidget implements Link {
 
+    private static final Stroke NORMAL_STROKE = new BasicStroke(1.0f);
+    private static final Stroke BOLD_STROKE = new BasicStroke(2.5f);
+    private static final Stroke DASHED_STROKE = new BasicStroke(1.0f, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10.0f, new float[]{5, 5}, 0);
+    private static final Stroke BOLD_DASHED_STROKE = new BasicStroke(2.5f, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10.0f, new float[]{5, 5}, 0);
+    
     private BlockWidget from;
     private BlockWidget to;
     private Port inputSlot;
     private Port outputSlot;
     private List<Point> points;
     private InputBlockEdge edge;
+    private boolean isDashed = false;
+    private boolean isBold = false;
 
     public BlockConnectionWidget(ControlFlowScene scene, InputBlockEdge edge) {
         super(scene);
@@ -67,6 +76,30 @@
         return outputSlot;
     }
 
+    public void setBold(boolean bold) {
+        this.isBold = bold;
+        updateStroke();
+    }
+
+    public void setDashed(boolean dashed) {
+        this.isDashed = dashed;
+        updateStroke();
+    }
+
+    private void updateStroke() {
+        Stroke stroke = NORMAL_STROKE;
+        if (isBold) {
+            if (isDashed) {
+                stroke = BOLD_DASHED_STROKE;
+            } else {
+                stroke = BOLD_STROKE;
+            }
+        } else if (isDashed) {
+            stroke = DASHED_STROKE;
+        }
+        setStroke(stroke);
+    }
+
     public void setControlPoints(List<Point> p) {
         this.points = p;
     }
--- a/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/BlockWidget.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/BlockWidget.java	Wed Jul 27 17:32:44 2011 -0700
@@ -31,6 +31,7 @@
 import java.awt.Dimension;
 import java.awt.Font;
 import java.awt.Point;
+import java.awt.Rectangle;
 import org.netbeans.api.visual.border.BorderFactory;
 import org.netbeans.api.visual.model.ObjectState;
 import org.netbeans.api.visual.widget.LabelWidget;
@@ -41,13 +42,13 @@
  */
 public class BlockWidget extends LabelWidget implements Vertex {
 
-    public static final Dimension SIZE = new Dimension(20, 20);
+    public static final Dimension MIN_SIZE = new Dimension(20, 20);
     private InputBlock block;
     private Port inputSlot;
     private Port outputSlot;
     private Cluster cluster;
     private boolean root;
-    private static final Font font = new Font(Font.SERIF, Font.PLAIN, 12);
+    private static final Font font = new Font(Font.SANS_SERIF, Font.PLAIN, 12);
     private static final Font boldFont = font.deriveFont(Font.BOLD);
     public static final Color NORMAL_FOREGROUND_COLOR = Color.BLACK;
     public static final Color HOVER_FOREGROUND_COLOR = Color.BLUE;
@@ -59,29 +60,24 @@
         this.setLabel(block.getName());
         this.setForeground(NORMAL_FOREGROUND_COLOR);
         this.setBorder(BorderFactory.createLineBorder(1, NORMAL_FOREGROUND_COLOR));
-        this.setMinimumSize(SIZE);
-        this.setMaximumSize(SIZE);
+        this.setMinimumSize(MIN_SIZE);
 
         this.setFont(font);
+        this.setAlignment(Alignment.CENTER);
 
         final BlockWidget widget = this;
         inputSlot = new Port() {
-
             public Point getRelativePosition() {
-                return new Point((int) (SIZE.getWidth() / 2), (int) (SIZE.getHeight() / 2));
+                return new Point((int) (getSize().getWidth() / 2), (int) (getSize().getHeight() / 2));
             }
-
             public Vertex getVertex() {
                 return widget;
             }
         };
-
         outputSlot = new Port() {
-
             public Point getRelativePosition() {
-                return new Point((int) (SIZE.getWidth() / 2), (int) (SIZE.getHeight() / 2));
+                return new Point((int) (getSize().getWidth() / 2), (int) (getSize().getHeight() / 2));
             }
-
             public Vertex getVertex() {
                 return widget;
             }
@@ -101,7 +97,12 @@
     }
 
     public Dimension getSize() {
-        return SIZE;
+        Rectangle bounds = getBounds();
+        if (bounds != null) {
+            return bounds.getSize();
+        } else {
+            return MIN_SIZE;
+        }
     }
 
     public void setPosition(Point p) {
--- a/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/Bundle.properties	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/Bundle.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -1,4 +1,4 @@
 CTL_ControlFlowAction=Open ControlFlow Window
-CTL_ControlFlowTopComponent=ControlFlow Window
-HINT_ControlFlowTopComponent=This is a ControlFlow window
+CTL_ControlFlowTopComponent=Control Flow
+HINT_ControlFlowTopComponent=Shows the blocks of the current graph.
 OpenIDE-Module-Name=ControlFlow
--- a/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowScene.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowScene.java	Wed Jul 27 17:32:44 2011 -0700
@@ -23,17 +23,17 @@
  */
 package com.sun.hotspot.igv.controlflow;
 
+import com.sun.hotspot.igv.data.InputBlockEdge;
 import com.sun.hotspot.igv.data.InputBlock;
-import com.sun.hotspot.igv.data.InputBlockEdge;
 import com.sun.hotspot.igv.data.InputGraph;
 import com.sun.hotspot.igv.data.services.InputGraphProvider;
 import com.sun.hotspot.igv.data.InputNode;
+import com.sun.hotspot.igv.util.LookupHistory;
 import java.awt.Color;
 import java.awt.Point;
 import java.awt.Rectangle;
 import java.util.ArrayList;
 import java.util.HashSet;
-import java.util.HashMap;
 import java.util.Set;
 import javax.swing.BorderFactory;
 import org.netbeans.api.visual.action.ActionFactory;
@@ -44,15 +44,14 @@
 import org.netbeans.api.visual.action.WidgetAction;
 import org.netbeans.api.visual.anchor.AnchorFactory;
 import org.netbeans.api.visual.anchor.AnchorShape;
-import org.netbeans.api.visual.layout.LayoutFactory;
 import org.netbeans.api.visual.router.RouterFactory;
 import org.netbeans.api.visual.widget.LayerWidget;
 import org.netbeans.api.visual.widget.Widget;
 import org.netbeans.api.visual.graph.GraphScene;
 import org.netbeans.api.visual.graph.layout.GraphLayout;
+import org.netbeans.api.visual.layout.LayoutFactory;
 import org.netbeans.api.visual.layout.SceneLayout;
 import org.netbeans.api.visual.widget.ConnectionWidget;
-import org.openide.util.Lookup;
 
 /**
  *
@@ -61,13 +60,12 @@
 public class ControlFlowScene extends GraphScene<InputBlock, InputBlockEdge> implements SelectProvider, MoveProvider, RectangularSelectDecorator, RectangularSelectProvider {
 
     private HashSet<BlockWidget> selection;
-    private HashMap<InputBlock, BlockWidget> blockMap;
     private InputGraph oldGraph;
     private LayerWidget edgeLayer;
     private LayerWidget mainLayer;
     private LayerWidget selectLayer;
     private WidgetAction hoverAction = this.createWidgetHoverAction();
-    private WidgetAction selectAction = ActionFactory.createSelectAction(this);
+    private WidgetAction selectAction = new DoubleClickSelectAction(this);
     private WidgetAction moveAction = ActionFactory.createMoveAction(null, this);
 
     public ControlFlowScene() {
@@ -81,7 +79,7 @@
 
         edgeLayer = new LayerWidget(this);
         this.addChild(edgeLayer);
-
+        
         selectLayer = new LayerWidget(this);
         this.addChild(selectLayer);
 
@@ -111,27 +109,21 @@
             addNode(b);
         }
 
-        for (InputBlock b : g.getBlocks()) {
-            for (InputBlockEdge e : b.getOutputs()) {
-                addEdge(e);
-                assert g.getBlocks().contains(e.getFrom());
-                assert g.getBlocks().contains(e.getTo());
-                this.setEdgeSource(e, e.getFrom());
-                this.setEdgeTarget(e, e.getTo());
-            }
+        for (InputBlockEdge e : g.getBlockEdges()) {
+            addEdge(e);
+            assert g.getBlocks().contains(e.getFrom());
+            assert g.getBlocks().contains(e.getTo());
+            this.setEdgeSource(e, e.getFrom());
+            this.setEdgeTarget(e, e.getTo());
         }
 
-        GraphLayout layout = new HierarchicalGraphLayout();//GridGraphLayout();
+        GraphLayout<InputBlock, InputBlockEdge> layout = new HierarchicalGraphLayout<InputBlock, InputBlockEdge>();//GridGraphLayout();
         SceneLayout sceneLayout = LayoutFactory.createSceneGraphLayout(this, layout);
         sceneLayout.invokeLayout();
 
         this.validate();
     }
 
-    public BlockWidget getBlockWidget(InputBlock b) {
-        return blockMap.get(b);
-    }
-
     public void clearSelection() {
         for (BlockWidget w : selection) {
             w.setState(w.getState().deriveSelected(false));
@@ -141,7 +133,7 @@
     }
 
     public void selectionChanged() {
-        InputGraphProvider p = Lookup.getDefault().lookup(InputGraphProvider.class);
+        InputGraphProvider p = LookupHistory.getLast(InputGraphProvider.class);//)Utilities.actionsGlobalContext().lookup(InputGraphProvider.class);
         if (p != null) {
             Set<InputNode> inputNodes = new HashSet<InputNode>();
             for (BlockWidget w : selection) {
@@ -204,15 +196,19 @@
     }
 
     public void setNewLocation(Widget widget, Point location) {
-        Point originalLocation = getOriginalLocation(widget);
-        int xOffset = location.x - originalLocation.x;
-        int yOffset = location.y - originalLocation.y;
-        for (Widget w : this.selection) {
-            Point p = new Point(w.getPreferredLocation());
-            p.translate(xOffset, yOffset);
-            w.setPreferredLocation(p);
+        if (selection.contains(widget)) {
+            // move entire selection
+            Point originalLocation = getOriginalLocation(widget);
+            int xOffset = location.x - originalLocation.x;
+            int yOffset = location.y - originalLocation.y;
+            for (Widget w : selection) {
+                Point p = new Point(w.getPreferredLocation());
+                p.translate(xOffset, yOffset);
+                w.setPreferredLocation(p);
+            }
+        } else {
+            widget.setPreferredLocation(location);
         }
-
     }
 
     public Widget createSelectionWidget() {
@@ -271,7 +267,15 @@
     }
 
     protected Widget attachEdgeWidget(InputBlockEdge edge) {
-        ConnectionWidget w = new BlockConnectionWidget(this, edge);
+        BlockConnectionWidget w = new BlockConnectionWidget(this, edge);
+        switch (edge.getState()) {
+            case NEW:
+                w.setBold(true);
+                break;
+            case DELETED:
+                w.setDashed(true);
+                break;
+        }
         w.setRouter(RouterFactory.createDirectRouter());
         w.setTargetAnchorShape(AnchorShape.TRIANGLE_FILLED);
         edgeLayer.addChild(w);
--- a/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowTopComponent.form	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowTopComponent.form	Wed Jul 27 17:32:44 2011 -0700
@@ -3,6 +3,8 @@
 <Form version="1.3" maxVersion="1.3" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
   <AuxValues>
     <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
     <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
     <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
     <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="2"/>
--- a/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowTopComponent.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowTopComponent.java	Wed Jul 27 17:32:44 2011 -0700
@@ -25,6 +25,7 @@
 
 import com.sun.hotspot.igv.data.InputGraph;
 import com.sun.hotspot.igv.data.services.InputGraphProvider;
+import com.sun.hotspot.igv.util.LookupHistory;
 import java.awt.BorderLayout;
 import java.io.Serializable;
 import javax.swing.JScrollPane;
@@ -39,7 +40,7 @@
 import org.openide.windows.WindowManager;
 
 /**
- *
+ * 
  * @author Thomas Wuerthinger
  */
 final class ControlFlowTopComponent extends TopComponent implements LookupListener {
@@ -63,17 +64,7 @@
         this.add(panel, BorderLayout.CENTER);
     }
 
-    @Override
-    public void requestFocus() {
-        super.requestFocus();
-        scene.getView().requestFocus();
-    }
 
-    @Override
-    public boolean requestFocusInWindow() {
-        super.requestFocusInWindow();
-        return scene.getView().requestFocusInWindow();
-    }
 
     /** This method is called from within the constructor to
      * initialize the form.
@@ -96,6 +87,7 @@
     }// </editor-fold>//GEN-END:initComponents
     // Variables declaration - do not modify//GEN-BEGIN:variables
     // End of variables declaration//GEN-END:variables
+
     /**
      * Gets default instance. Do not use directly: reserved for *.settings files only,
      * i.e. deserialization routines; otherwise you could get a non-deserialized instance.
@@ -131,7 +123,7 @@
 
     @Override
     public void componentOpened() {
-        Lookup.Template tpl = new Lookup.Template(Object.class);
+        Lookup.Template<InputGraphProvider> tpl = new Lookup.Template<InputGraphProvider>(InputGraphProvider.class);
         result = Utilities.actionsGlobalContext().lookup(tpl);
         result.addLookupListener(this);
     }
@@ -143,16 +135,16 @@
     }
 
     public void resultChanged(LookupEvent lookupEvent) {
-
-        final InputGraphProvider p = Lookup.getDefault().lookup(InputGraphProvider.class);
+        final InputGraphProvider p = LookupHistory.getLast(InputGraphProvider.class);//Utilities.actionsGlobalContext().lookup(InputGraphProvider.class);
         if (p != null) {
             SwingUtilities.invokeLater(new Runnable() {
+
                 public void run() {
-            InputGraph g = p.getGraph();
-            if (g != null) {
-                scene.setGraph(g);
-            }
-        }
+                    InputGraph g = p.getGraph();
+                    if (g != null) {
+                        scene.setGraph(g);
+                    }
+                }
             });
         }
     }
@@ -169,8 +161,8 @@
 
     @Override
     public void requestActive() {
-        scene.getView().requestFocusInWindow();
         super.requestActive();
+        scene.getView().requestFocus();
     }
 
     final static class ResolvableHelper implements Serializable {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/DoubleClickSelectAction.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,61 @@
+/*
+ * 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.sun.hotspot.igv.controlflow;
+
+import java.awt.Point;
+import java.awt.event.MouseEvent;
+import org.netbeans.api.visual.action.SelectProvider;
+import org.netbeans.api.visual.action.WidgetAction;
+import org.netbeans.api.visual.widget.Widget;
+
+/**
+ * Selection action that acts on double-click only. Does not support aiming.
+ * 
+ * @author Peter Hofer
+ */
+public class DoubleClickSelectAction extends WidgetAction.LockedAdapter {
+
+    private final SelectProvider provider;
+
+    public DoubleClickSelectAction(SelectProvider provider) {
+        this.provider = provider;
+    }
+
+    protected boolean isLocked() {
+        return false;
+    }
+
+    @Override
+    public State mousePressed(Widget widget, WidgetMouseEvent event) {
+        if (event.getClickCount() >= 2 && (event.getButton() == MouseEvent.BUTTON1 || event.getButton() == MouseEvent.BUTTON2)) {
+            boolean invert = (event.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) != 0;
+            Point point = event.getPoint();
+            if (provider.isSelectionAllowed(widget, point, invert)) {
+                provider.select(widget, point, invert);
+                return State.CHAIN_ONLY;
+            }
+        }
+        return State.REJECTED;
+    }
+}
--- a/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/HierarchicalGraphLayout.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/HierarchicalGraphLayout.java	Wed Jul 27 17:32:44 2011 -0700
@@ -34,7 +34,7 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
-import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -127,6 +127,7 @@
         }
 
         public int compareTo(Vertex o) {
+            @SuppressWarnings("unchecked")
             VertexWrapper vw = (VertexWrapper) o;
             return node.toString().compareTo(vw.node.toString());
         }
@@ -137,9 +138,9 @@
     }
 
     protected void performGraphLayout(UniversalGraph<N, E> graph) {
-
-        Set<LinkWrapper> links = new HashSet<LinkWrapper>();
-        Set<VertexWrapper> vertices = new HashSet<VertexWrapper>();
+        
+        Set<LinkWrapper> links = new LinkedHashSet<LinkWrapper>();
+        Set<VertexWrapper> vertices = new LinkedHashSet<VertexWrapper>();
         Map<N, VertexWrapper> vertexMap = new HashMap<N, VertexWrapper>();
 
         for (N node : graph.getNodes()) {
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/nbproject/project.xml	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/nbproject/project.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -44,7 +44,15 @@
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>1</release-version>
-                        <specification-version>1.10.0.1</specification-version>
+                        <specification-version>1.23.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.spi.quicksearch</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -52,7 +60,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.6.1.1</specification-version>
+                        <specification-version>6.21.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -60,7 +68,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.11.0.1</specification-version>
+                        <specification-version>7.30.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -68,7 +76,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.5.1</specification-version>
+                        <specification-version>7.18.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -76,7 +84,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.11</specification-version>
+                        <specification-version>6.34.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -84,7 +92,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.3</specification-version>
+                        <specification-version>7.46.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -92,7 +100,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.7</specification-version>
+                        <specification-version>7.20.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -100,7 +108,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.2.0.1</specification-version>
+                        <specification-version>7.20.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -108,7 +116,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.9.0.1</specification-version>
+                        <specification-version>8.14.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.lookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.6.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -116,7 +132,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.16</specification-version>
+                        <specification-version>6.39.1</specification-version>
                     </run-dependency>
                 </dependency>
             </module-dependencies>
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/Bundle.properties	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/Bundle.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -1,7 +1,9 @@
 
 AdvancedOption_DisplayName_Coordinator=Settings
 AdvancedOption_Tooltip_Coordinator=Visualization Tool Settings
-CTL_OutlineTopComponent=Outline Window
+CTL_OutlineTopComponent=Outline
 CTL_SomeAction=test
-HINT_OutlineTopComponent=This is a Outline window
+HINT_OutlineTopComponent=Displays loaded groups of graphs.
 OpenIDE-Module-Name=Coordinator
+Toolbars/QuickSearch=Quick Search
+QuickSearch/Nodes/com-sun-hotspot-igv-coordinator-QuickSearch.instance=Nodes
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/FolderNode.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/FolderNode.java	Wed Jul 27 17:32:44 2011 -0700
@@ -25,6 +25,7 @@
 
 import com.sun.hotspot.igv.coordinator.actions.RemoveCookie;
 import com.sun.hotspot.igv.data.ChangedListener;
+import com.sun.hotspot.igv.data.GraphDocument;
 import com.sun.hotspot.igv.data.Group;
 import com.sun.hotspot.igv.data.services.GroupOrganizer;
 import com.sun.hotspot.igv.data.InputGraph;
@@ -35,7 +36,7 @@
 import org.openide.nodes.AbstractNode;
 import org.openide.nodes.Children;
 import org.openide.nodes.Node;
-import org.openide.util.Utilities;
+import org.openide.util.ImageUtilities;
 import org.openide.util.lookup.AbstractLookup;
 import org.openide.util.lookup.InstanceContent;
 
@@ -51,10 +52,15 @@
     private List<String> subFolders;
     private FolderChildren children;
 
-    private static class FolderChildren extends Children.Keys implements ChangedListener<Group> {
+    private static class FolderChildren extends Children.Keys<Pair<String, List<Group>>> implements ChangedListener<Group> {
 
         private FolderNode parent;
         private List<Group> registeredGroups;
+        private GraphDocument document;
+
+        public FolderChildren(GraphDocument document) {
+            this.document = document;
+        }
 
         public void setParent(FolderNode parent) {
             this.parent = parent;
@@ -62,14 +68,13 @@
         }
 
         @Override
-        protected Node[] createNodes(Object arg0) {
+        protected Node[] createNodes(Pair<String, List<Group>> p) {
 
             for(Group g : registeredGroups) {
                 g.getChangedEvent().removeListener(this);
             }
             registeredGroups.clear();
-
-            Pair<String, List<Group>> p = (Pair<String, List<Group>>) arg0;
+            
             if (p.getLeft().length() == 0) {
 
                 List<Node> curNodes = new ArrayList<Node>();
@@ -88,7 +93,7 @@
                 return result;
 
             } else {
-                return new Node[]{new FolderNode(p.getLeft(), parent.organizer, parent.subFolders, p.getRight())};
+                return new Node[]{new FolderNode(document, p.getLeft(), parent.organizer, parent.subFolders, p.getRight())};
             }
         }
 
@@ -96,13 +101,12 @@
         public void addNotify() {
             this.setKeys(parent.structure);
         }
-
+        
         public void changed(Group source) {
-            List<Pair<String, List<Group>>> newStructure = new ArrayList<Pair<String, List<Group>>>();
             for(Pair<String, List<Group>> p : parent.structure) {
                 refreshKey(p);
             }
-        }
+         }
     }
 
     protected InstanceContent getContent() {
@@ -111,14 +115,14 @@
 
     @Override
     public Image getIcon(int i) {
-        return Utilities.loadImage("com/sun/hotspot/igv/coordinator/images/folder.gif");
+        return ImageUtilities.loadImage("com/sun/hotspot/igv/coordinator/images/folder.png");
     }
 
-    protected FolderNode(String name, GroupOrganizer organizer, List<String> subFolders, List<Group> groups) {
-        this(name, organizer, subFolders, groups, new FolderChildren(), new InstanceContent());
+    protected FolderNode(GraphDocument document, String name, GroupOrganizer organizer, List<String> subFolders, List<Group> groups) {
+        this(document, name, organizer, subFolders, groups, new FolderChildren(document), new InstanceContent());
     }
 
-    private FolderNode(String name, GroupOrganizer organizer, List<String> oldSubFolders, final List<Group> groups, FolderChildren children, InstanceContent content) {
+    private FolderNode(final GraphDocument document, String name, GroupOrganizer organizer, List<String> oldSubFolders, final List<Group> groups, FolderChildren children, InstanceContent content) {
         super(children, new AbstractLookup(content));
         children.setParent(this);
         this.content = content;
@@ -127,9 +131,8 @@
 
             public void remove() {
                 for (Group g : groups) {
-                    if (g.getDocument() != null) {
-                        g.getDocument().removeGroup(g);
-                    }
+                    document.removeGroup(g);
+                    
                 }
             }
         });
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/GraphCountGroupOrganizer.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/GraphCountGroupOrganizer.java	Wed Jul 27 17:32:44 2011 -0700
@@ -49,7 +49,7 @@
         List<Pair<String, List<Group>>> result = new ArrayList<Pair<String, List<Group>>>();
 
         if (subFolders.size() == 0) {
-            Map<Integer, List<Group>> map = new HashMap<Integer, List<Group>>();
+            Map<Integer, List<Group>> map = new HashMap<Integer, List<Group>>(groups.size());
             for (Group g : groups) {
                 Integer cur = g.getGraphs().size();
                 if (!map.containsKey(cur)) {
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/GraphNode.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/GraphNode.java	Wed Jul 27 17:32:44 2011 -0700
@@ -25,10 +25,12 @@
 
 import com.sun.hotspot.igv.coordinator.actions.DiffGraphAction;
 import com.sun.hotspot.igv.coordinator.actions.DiffGraphCookie;
+import com.sun.hotspot.igv.coordinator.actions.GraphOpenCookie;
+import com.sun.hotspot.igv.coordinator.actions.GraphRemoveCookie;
 import com.sun.hotspot.igv.coordinator.actions.RemoveCookie;
 import com.sun.hotspot.igv.data.InputGraph;
+import com.sun.hotspot.igv.data.Properties;
 import com.sun.hotspot.igv.data.services.GraphViewer;
-import com.sun.hotspot.igv.data.services.InputGraphProvider;
 import com.sun.hotspot.igv.util.PropertiesSheet;
 import java.awt.Image;
 import javax.swing.Action;
@@ -36,10 +38,9 @@
 import org.openide.cookies.OpenCookie;
 import org.openide.nodes.AbstractNode;
 import org.openide.nodes.Children;
-import org.openide.nodes.Node;
 import org.openide.nodes.Sheet;
+import org.openide.util.ImageUtilities;
 import org.openide.util.Lookup;
-import org.openide.util.Utilities;
 import org.openide.util.lookup.AbstractLookup;
 import org.openide.util.lookup.InstanceContent;
 
@@ -66,33 +67,30 @@
 
         if (viewer != null) {
             // Action for opening the graph
-            content.add(new OpenCookie() {
-
-                public void open() {
-                    viewer.view(graph);
-                }
-            });
+            content.add(new GraphOpenCookie(viewer, graph));
         }
 
         // Action for removing a graph
-        content.add(new RemoveCookie() {
+        content.add(new GraphRemoveCookie(graph));
 
-            public void remove() {
-                graph.getGroup().removeGraph(graph);
-            }
-        });
+        // Action for diffing to the current graph
+        content.add(new DiffGraphCookie(graph));
     }
 
     @Override
     protected Sheet createSheet() {
         Sheet s = super.createSheet();
-        PropertiesSheet.initializeSheet(graph.getProperties(), s);
+        Properties p = new Properties();
+        p.add(graph.getProperties());
+        p.setProperty("nodeCount", Integer.toString(graph.getNodes().size()));
+        p.setProperty("edgeCount", Integer.toString(graph.getEdges().size()));
+        PropertiesSheet.initializeSheet(p, s);
         return s;
     }
 
     @Override
     public Image getIcon(int i) {
-        return Utilities.loadImage("com/sun/hotspot/igv/coordinator/images/graph.gif");
+        return ImageUtilities.loadImage("com/sun/hotspot/igv/coordinator/images/graph.png");
     }
 
     @Override
@@ -101,24 +99,6 @@
     }
 
     @Override
-    public <T extends Node.Cookie> T getCookie(Class<T> aClass) {
-        if (aClass == DiffGraphCookie.class) {
-            InputGraphProvider graphProvider = Utilities.actionsGlobalContext().lookup(InputGraphProvider.class);
-
-            InputGraph graphA = null;
-            if (graphProvider != null) {
-                graphA = graphProvider.getGraph();
-            }
-
-            if (graphA != null && !graphA.isDifferenceGraph()) {
-                return (T) new DiffGraphCookie(graphA, graph);
-            }
-        }
-
-        return super.getCookie(aClass);
-    }
-
-    @Override
     public Action[] getActions(boolean b) {
         return new Action[]{(Action) DiffGraphAction.findObject(DiffGraphAction.class, true), (Action) OpenAction.findObject(OpenAction.class, true)};
     }
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/OutlineTopComponent.form	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/OutlineTopComponent.form	Wed Jul 27 17:32:44 2011 -0700
@@ -3,6 +3,8 @@
 <Form version="1.2" maxVersion="1.2" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
   <AuxValues>
     <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
     <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
     <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
     <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="2"/>
@@ -23,7 +25,7 @@
 
       <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
       <SubComponents>
-        <Container class="javax.swing.JScrollPane" name="jScrollPane1">
+        <Container class="javax.swing.JScrollPane" name="treeView">
           <AuxValues>
             <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new BeanTreeView();"/>
           </AuxValues>
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/OutlineTopComponent.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/OutlineTopComponent.java	Wed Jul 27 17:32:44 2011 -0700
@@ -62,7 +62,7 @@
 import org.openide.windows.WindowManager;
 
 /**
- *
+ * 
  * @author Thomas Wuerthinger
  */
 public final class OutlineTopComponent extends TopComponent implements ExplorerManager.Provider, LookupListener {
@@ -89,9 +89,9 @@
     private void initListView() {
         manager = new ExplorerManager();
         organizer = new StandardGroupOrganizer();
-        root = new FolderNode("", organizer, new ArrayList<String>(), document.getGroups());
+        root = new FolderNode(document, "", organizer, new ArrayList<String>(), document.getGroups());
         manager.setRootContext(root);
-        ((BeanTreeView) this.jScrollPane1).setRootVisible(false);
+        ((BeanTreeView) this.treeView).setRootVisible(false);
 
         document.getChangedEvent().addListener(new ChangedListener<GraphDocument>() {
 
@@ -122,8 +122,6 @@
         for (Toolbar tb : ToolbarPool.getDefault().getToolbars()) {
             tb.setVisible(false);
         }
-
-        initOrganizers();
     }
 
     public void setOrganizer(GroupOrganizer organizer) {
@@ -131,10 +129,6 @@
         updateStructure();
     }
 
-    private void initOrganizers() {
-
-    }
-
     private void initReceivers() {
 
         final GroupCallback callback = new GroupCallback() {
@@ -221,6 +215,24 @@
         return PREFERRED_ID;
     }
 
+    @Override
+    public void requestActive() {
+        super.requestActive();
+        treeView.requestFocus();
+    }
+
+    @Override
+    public boolean requestFocus(boolean temporary) {
+        treeView.requestFocus();
+        return super.requestFocus(temporary);
+    }
+
+    @Override
+    protected boolean requestFocusInWindow(boolean temporary) {
+        treeView.requestFocus();
+        return super.requestFocusInWindow(temporary);
+    }
+
     public void resultChanged(LookupEvent lookupEvent) {
     }
 
@@ -228,7 +240,7 @@
     public void readExternal(ObjectInput objectInput) throws IOException, ClassNotFoundException {
         // Not called when user starts application for the first time
         super.readExternal(objectInput);
-        ((BeanTreeView) this.jScrollPane1).setRootVisible(false);
+        ((BeanTreeView) this.treeView).setRootVisible(false);
     }
 
     @Override
@@ -254,18 +266,18 @@
     private void initComponents() {
 
         jPanel2 = new javax.swing.JPanel();
-        jScrollPane1 = new BeanTreeView();
+        treeView = new BeanTreeView();
 
         setLayout(new java.awt.BorderLayout());
 
         jPanel2.setLayout(new java.awt.BorderLayout());
-        jPanel2.add(jScrollPane1, java.awt.BorderLayout.CENTER);
+        jPanel2.add(treeView, java.awt.BorderLayout.CENTER);
 
         add(jPanel2, java.awt.BorderLayout.CENTER);
     }// </editor-fold>//GEN-END:initComponents
 
     // Variables declaration - do not modify//GEN-BEGIN:variables
     private javax.swing.JPanel jPanel2;
-    private javax.swing.JScrollPane jScrollPane1;
+    private javax.swing.JScrollPane treeView;
     // End of variables declaration//GEN-END:variables
 }
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/StandardGroupOrganizer.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/StandardGroupOrganizer.java	Wed Jul 27 17:32:44 2011 -0700
@@ -28,6 +28,7 @@
 import com.sun.hotspot.igv.data.services.GroupOrganizer;
 import com.sun.hotspot.igv.data.Pair;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -41,22 +42,17 @@
     }
 
     public List<Pair<String, List<Group>>> organize(List<String> subFolders, List<Group> groups) {
-
         List<Pair<String, List<Group>>> result = new ArrayList<Pair<String, List<Group>>>();
-
         if (groups.size() == 1 && subFolders.size() > 0) {
             result.add(new Pair<String, List<Group>>("", groups));
         } else {
             for (Group g : groups) {
-                List<Group> children = new ArrayList<Group>();
-                children.add(g);
                 Pair<String, List<Group>> p = new Pair<String, List<Group>>();
                 p.setLeft(g.getName());
-                p.setRight(children);
+                p.setRight(Arrays.asList(g));
                 result.add(p);
             }
         }
-
         return result;
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/Bundle.properties	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/Bundle.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -1,18 +1,9 @@
-CTL_EditFilterAction=Edit...
 CTL_ImportAction=Open...
 CTL_OpenGraphAction=View graph
 CTL_DiffGraphAction=Difference to current graph
 CTL_RemoveAction=Remove methods
-CTL_ApplyFilterAction=Apply
-CTL_FilterAction=Open Filter Window
-CTL_AppliedFilterAction=Open AppliedFilter Window
-CTL_OutlineAction=Open Outline Window
-CTL_MoveFilterUpAction=Move upwards
-CTL_MoveFilterDownAction=Move downwards
-CTL_RemoveFilterAction=Remove
-CTL_RemoveFilterSettingsAction=Remove filter setting
+CTL_OutlineAction=Open Outline Window 
 CTL_SaveAsAction=Save selected methods...
 CTL_SaveAllAction=Save all...
-CTL_SaveFilterSettingsAction=Save filter settings...
-CTL_PropertiesAction=Open Properties Window
+CTL_PropertiesAction=Open Properties Window 
 CTL_NewFilterAction=New filter...
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/DiffGraphAction.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/DiffGraphAction.java	Wed Jul 27 17:32:44 2011 -0700
@@ -37,6 +37,7 @@
 
     protected void performAction(Node[] activatedNodes) {
         DiffGraphCookie c = activatedNodes[0].getCookie(DiffGraphCookie.class);
+        assert c != null;
         c.openDiff();
     }
 
@@ -44,6 +45,19 @@
         return CookieAction.MODE_EXACTLY_ONE;
     }
 
+    @Override
+    protected boolean enable(Node[] activatedNodes) {
+        boolean b = super.enable(activatedNodes);
+        if (b) {
+            assert activatedNodes.length == 1;
+            DiffGraphCookie c = activatedNodes[0].getCookie(DiffGraphCookie.class);
+            assert c != null;
+            return c.isPossible();
+        }
+
+        return false;
+    }
+
     public String getName() {
         return NbBundle.getMessage(DiffGraphAction.class, "CTL_DiffGraphAction");
     }
@@ -56,7 +70,7 @@
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/coordinator/images/diff.gif";
+        return "com/sun/hotspot/igv/coordinator/images/diff.png";
     }
 
     public HelpCtx getHelpCtx() {
@@ -68,3 +82,4 @@
         return false;
     }
 }
+
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/DiffGraphCookie.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/DiffGraphCookie.java	Wed Jul 27 17:32:44 2011 -0700
@@ -21,12 +21,16 @@
  * questions.
  *
  */
-
 package com.sun.hotspot.igv.coordinator.actions;
 
 import com.sun.hotspot.igv.data.InputGraph;
 import com.sun.hotspot.igv.data.services.GraphViewer;
+import com.sun.hotspot.igv.data.services.InputGraphProvider;
 import com.sun.hotspot.igv.difference.Difference;
+import com.sun.hotspot.igv.util.LookupHistory;
+import org.openide.DialogDescriptor;
+import org.openide.DialogDisplayer;
+import org.openide.NotifyDescriptor;
 import org.openide.nodes.Node;
 import org.openide.util.Lookup;
 
@@ -36,20 +40,39 @@
  */
 public class DiffGraphCookie implements Node.Cookie {
 
-    private InputGraph a;
-    private InputGraph b;
+    private InputGraph graph;
+
+    public DiffGraphCookie(InputGraph graph) {
+        this.graph = graph;
+    }
 
-    public DiffGraphCookie(InputGraph a, InputGraph b) {
-        this.a = a;
-        this.b = b;
+    private InputGraph getCurrentGraph() {
+        InputGraphProvider graphProvider = LookupHistory.getLast(InputGraphProvider.class);
+        if (graphProvider != null) {
+            return graphProvider.getGraph();
+        }
+        return null;
+    }
+
+    public boolean isPossible() {
+        return getCurrentGraph() != null;
     }
 
     public void openDiff() {
+        InputGraph other = getCurrentGraph();
+
+        if (!graph.getGroup().isComplete() || !other.getGroup().isComplete()) {
+            String msg = "One of the graphs or the groups they belong to are still being loaded. Creating a diff now can cause problems. Do you want to continue?";
+            NotifyDescriptor desc = new NotifyDescriptor(msg, "Incomplete data", NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.QUESTION_MESSAGE, null, NotifyDescriptor.NO_OPTION);
+
+            if (DialogDisplayer.getDefault().notify(desc) == DialogDescriptor.NO_OPTION) {
+                return;
+            }
+        }
 
         final GraphViewer viewer = Lookup.getDefault().lookup(GraphViewer.class);
-
-        if(viewer != null) {
-            InputGraph diffGraph = Difference.createDiffGraph(a, b);
+        if (viewer != null) {
+            InputGraph diffGraph = Difference.createDiffGraph(other, graph);
             viewer.view(diffGraph);
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/GraphOpenCookie.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,55 @@
+/*
+ * 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.sun.hotspot.igv.coordinator.actions;
+
+import com.sun.hotspot.igv.data.InputGraph;
+import com.sun.hotspot.igv.data.services.GraphViewer;
+import org.openide.DialogDescriptor;
+import org.openide.DialogDisplayer;
+import org.openide.NotifyDescriptor;
+import org.openide.cookies.OpenCookie;
+
+public class GraphOpenCookie implements OpenCookie {
+
+    private final GraphViewer viewer;
+    private final InputGraph graph;
+
+    public GraphOpenCookie(GraphViewer viewer, InputGraph graph) {
+        this.viewer = viewer;
+        this.graph = graph;
+    }
+
+    public void open() {
+        if (!graph.getGroup().isComplete()) {
+            String msg = "This graph or the group it belongs to is still being loaded. Opening this graph now can cause problems. Do you want to continue and open the graph?";
+            NotifyDescriptor desc = new NotifyDescriptor(msg, "Incomplete data", NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.QUESTION_MESSAGE, null, NotifyDescriptor.NO_OPTION);
+
+            if (DialogDisplayer.getDefault().notify(desc) == DialogDescriptor.NO_OPTION) {
+                return;
+            }
+        }
+
+        viewer.view(graph);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/GraphRemoveCookie.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,51 @@
+/*
+ * 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.sun.hotspot.igv.coordinator.actions;
+
+import com.sun.hotspot.igv.data.InputGraph;
+import org.openide.DialogDescriptor;
+import org.openide.DialogDisplayer;
+import org.openide.NotifyDescriptor;
+
+public class GraphRemoveCookie implements RemoveCookie {
+
+    private final InputGraph graph;
+
+    public GraphRemoveCookie(InputGraph graph) {
+        this.graph = graph;
+    }
+
+    public void remove() {
+        if (!graph.getGroup().isComplete()) {
+            String msg = "This graph or the group it belongs to is still being loaded. Removing this graph now can cause problems. Do you want to continue and remove the graph?";
+            NotifyDescriptor desc = new NotifyDescriptor(msg, "Incomplete data", NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.QUESTION_MESSAGE, null, NotifyDescriptor.NO_OPTION);
+
+            if (DialogDisplayer.getDefault().notify(desc) == DialogDescriptor.NO_OPTION) {
+                return;
+            }
+        }
+
+        graph.getGroup().removeGraph(graph);
+    }
+}
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/ImportAction.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/ImportAction.java	Wed Jul 27 17:32:44 2011 -0700
@@ -161,7 +161,7 @@
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/coordinator/images/import.gif";
+        return "com/sun/hotspot/igv/coordinator/images/import.png";
     }
 
     public HelpCtx getHelpCtx() {
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/RemoveAction.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/RemoveAction.java	Wed Jul 27 17:32:44 2011 -0700
@@ -55,7 +55,7 @@
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/coordinator/images/remove.gif";
+        return "com/sun/hotspot/igv/coordinator/images/remove.png";
     }
 
     public HelpCtx getHelpCtx() {
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/RemoveAllAction.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/RemoveAllAction.java	Wed Jul 27 17:32:44 2011 -0700
@@ -51,7 +51,7 @@
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/coordinator/images/removeall.gif";
+        return "com/sun/hotspot/igv/coordinator/images/removeall.png";
     }
 
     public HelpCtx getHelpCtx() {
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/SaveAsAction.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/SaveAsAction.java	Wed Jul 27 17:32:44 2011 -0700
@@ -98,7 +98,7 @@
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/coordinator/images/save.gif";
+        return "com/sun/hotspot/igv/coordinator/images/save.png";
     }
 
     public HelpCtx getHelpCtx() {
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/StructuredViewAction.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/StructuredViewAction.java	Wed Jul 27 17:32:44 2011 -0700
@@ -51,8 +51,8 @@
 import javax.swing.event.PopupMenuListener;
 import org.openide.awt.DropDownButtonFactory;
 import org.openide.util.HelpCtx;
+import org.openide.util.ImageUtilities;
 import org.openide.util.Lookup;
-import org.openide.util.Utilities;
 import org.openide.util.actions.CallableSystemAction;
 
 public class StructuredViewAction extends CallableSystemAction {
@@ -71,7 +71,7 @@
     @Override
     public Component getToolbarPresenter() {
 
-        Image iconImage = Utilities.loadImage("com/sun/hotspot/igv/coordinator/images/structure.gif");
+        Image iconImage = ImageUtilities.loadImage("com/sun/hotspot/igv/coordinator/images/structure.png");
         ImageIcon icon = new ImageIcon(iconImage);
 
         popup = new JPopupMenu();
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/customLeftWsmode.xml	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/customLeftWsmode.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -4,12 +4,8 @@
     <kind type="view" />
     <state type="joined" />
     <constraints>
-        <path orientation="horizontal" number="0" weight="0.779245283018868"/>
-        <path orientation="vertical" number="0" weight="0.7511825922421949"/>
-        <path orientation="horizontal" number="0" weight="0.5"/>
-        <path orientation="vertical" number="20" weight="0.7"/>
-        <path orientation="horizontal" number="40" weight="0.55"/>
-        <path orientation="horizontal" number="0" weight="0.2711864406779661"/>
+        <path orientation="horizontal" number="0" weight="0.2"/>
+        <path orientation="vertical" number="0" weight="0.75"/>
     </constraints>
     <bounds x="0" y="0" width="0" height="0" />
     <frame state="0"/>
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/diff.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/diff.png has changed
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/folder.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/folder.png has changed
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/graph.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/graph.png has changed
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/import.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/import.png has changed
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/remove.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/remove.png has changed
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/removeall.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/removeall.png has changed
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/save.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/save.png has changed
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/saveall.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/structure.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/structure.png has changed
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/layer.xml	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/layer.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd">
+<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
 <filesystem>
     <attr name="Actions\Edit\com-sun-hotspot-igv-bytecodes-SelectBytecodesAction.instance\position" intvalue="200"/>
     <attr name="Actions\Edit\org-netbeans-core-ui-sysopen-SystemOpenAction.instance\position" intvalue="100"/>
@@ -12,7 +12,7 @@
     <attr name="Actions\Edit\org-openide-actions-RedoAction.instance\position" intvalue="1900"/>
     <attr name="Actions\Edit\org-openide-actions-ReplaceAction.instance\position" intvalue="2000"/>
     <attr name="Actions\Edit\org-openide-actions-UndoAction.instance\position" intvalue="2100"/>
-
+    
     <folder name="Actions">
         <folder name="File">
             <file name="com-sun-hotspot-igv-coordinator-actions-SaveAsAction.instance">
@@ -26,7 +26,7 @@
             </file>
         </folder>
         <folder name="Edit">
-
+            
             <file name="com-sun-hotspot-igv-coordinator-actions-RemoveAction.instance">
                 <attr name="position" intvalue="1200"/>
             </file>
@@ -57,7 +57,7 @@
                 <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
                 <attr name="position" intvalue="500"/>
             </file>
-
+            
             <file name="org-netbeans-modules-openfile-OpenFileAction.instance_hidden"/>
             <file name="org-openide-actions-PageSetupAction.instance_hidden"/>
             <file name="org-openide-actions-PrintAction.instance_hidden"/>
@@ -96,15 +96,21 @@
                 <attr name="originalFile" stringvalue="Actions/Window/com-sun-hotspot-igv-coordinator-actions-OutlineAction.instance"/>
             </file>
         </folder>
-    </folder>
-    <folder name="Toolbars">
-        <file name="Standard.xml" url="StandardConfiguration.xml"/>
-    </folder>
+        
+        <file name="Spacer.instance">
+            <attr name="instanceCreate" methodvalue="javax.swing.Box.createHorizontalGlue"/>
+            <attr name="position" intvalue="9980"/>
+        </file>
+            <file name="org-netbeans-modules-quicksearch-QuickSearchAction.shadow">
+            <attr name="displayName" bundlevalue="com.sun.hotspot.igv.coordinator.Bundle#Toolbars/QuickSearch"/>
+            <attr name="originalFile" stringvalue="Actions/Edit/org-netbeans-modules-quicksearch-QuickSearchAction.instance"/>
+            </file>
+        </folder>
     <folder name="Windows2">
         <folder name="Components">
             <file name="OutlineTopComponent.settings" url="OutlineTopComponentSettings.xml"/>
         </folder>
-        <folder name="Modes">
+        <folder name="Modes">  
             <file name="customLeft.wsmode" url="customLeftWsmode.xml"/>
             <folder name="customLeft">
                 <file name="OutlineTopComponent.wstcref" url="OutlineTopComponentWstcref.xml"/>
--- a/src/share/tools/IdealGraphVisualizer/Data/manifest.mf	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Data/manifest.mf	Wed Jul 27 17:32:44 2011 -0700
@@ -1,5 +1,5 @@
-Manifest-Version: 1.0
-OpenIDE-Module: com.sun.hotspot.igv.data
-OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/data/Bundle.properties
-OpenIDE-Module-Specification-Version: 1.0
-
+Manifest-Version: 1.0
+OpenIDE-Module: com.sun.hotspot.igv.data
+OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/data/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
--- a/src/share/tools/IdealGraphVisualizer/Data/nbproject/project.properties	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Data/nbproject/project.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -1,2 +1,8 @@
 javac.source=1.5
 javac.compilerargs=-Xlint -Xlint:-serial
+src.dir=src
+build.test.classes.dir=${build.dir}/test/classes
+build.test.results.dir=${build.dir}/test/results
+test.src.dir=test
+build.test.classes.dir=${build.dir}/test/classes
+build.test.results.dir=${build.dir}/test/results
--- a/src/share/tools/IdealGraphVisualizer/Data/nbproject/project.xml	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Data/nbproject/project.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -6,6 +6,19 @@
             <code-name-base>com.sun.hotspot.igv.data</code-name-base>
             <suite-component/>
             <module-dependencies/>
+            <test-dependencies>
+                <test-type>
+                    <name>unit</name>
+                    <test-dependency>
+                        <code-name-base>org.netbeans.libs.junit4</code-name-base>
+                        <compile-dependency/>
+                    </test-dependency>
+                    <test-dependency>
+                        <code-name-base>org.openide.util</code-name-base>
+                        <compile-dependency/>
+                    </test-dependency>
+                </test-type>
+            </test-dependencies>
             <public-packages>
                 <package>com.sun.hotspot.igv.data</package>
                 <package>com.sun.hotspot.igv.data.serialization</package>
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/ChangedEvent.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/ChangedEvent.java	Wed Jul 27 17:32:44 2011 -0700
@@ -24,16 +24,17 @@
 package com.sun.hotspot.igv.data;
 
 /**
- *
+ * Class representing a generic changed event.
  * @author Thomas Wuerthinger
+ * @param <T>
  */
 public class ChangedEvent<T> extends Event<ChangedListener<T>> {
 
     private T object;
 
-    public ChangedEvent() {
-    }
-
+    /**
+     * Creates a new event with the specific object as the one for which the event gets fired.
+     */
     public ChangedEvent(T object) {
         this.object = object;
     }
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/ChangedEventProvider.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/ChangedEventProvider.java	Wed Jul 27 17:32:44 2011 -0700
@@ -25,10 +25,14 @@
 package com.sun.hotspot.igv.data;
 
 /**
- *
+ * Provides a changed event object.
  * @author Thomas Wuerthinger
+ * @param <T> Class for which the changed event fires.
  */
 public interface ChangedEventProvider<T> {
 
-    public ChangedEvent<T> getChangedEvent();
+    /**
+     * Returns the changed event object. Should always return the same instance.
+     */
+    ChangedEvent<T> getChangedEvent();
 }
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/ChangedListener.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/ChangedListener.java	Wed Jul 27 17:32:44 2011 -0700
@@ -24,10 +24,15 @@
 package com.sun.hotspot.igv.data;
 
 /**
- *
+ * Listens to changed events.
  * @author Thomas Wuerthinger
+ * @param <T> Class for which the changed event fires.
  */
 public interface ChangedListener<T> {
 
-    public void changed(T source);
+    /**
+     * This method is called everytime a changed event is fired.
+     * @param source Object that has changed.
+     */
+    void changed(T source);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/ControllableChangedListener.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package com.sun.hotspot.igv.data;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public abstract class ControllableChangedListener<T> implements ChangedListener<T>{
+
+	private boolean enabled;
+
+	
+	public ControllableChangedListener() {
+		enabled = true;
+	}
+
+	public boolean isEnabled() {
+		return enabled;
+	}
+
+	public void setEnabled(boolean b) {
+		enabled = b;
+	}
+
+	public void changed(T source) {
+		if(enabled) {
+			filteredChanged(source);
+		}
+	}
+
+	public abstract void filteredChanged(T source);
+}
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Event.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Event.java	Wed Jul 27 17:32:44 2011 -0700
@@ -33,25 +33,50 @@
 public abstract class Event<L> {
 
     private List<L> listener;
-
+    private boolean fireEvents;
+    private boolean eventWasFired;
+    
     public Event() {
         listener = new ArrayList<L>();
+        fireEvents = true;
     }
 
     public void addListener(L l) {
         listener.add(l);
     }
 
-    public void removeListener(L l) {
+    /**
+     * Remove listener
+     * @param l
+     */
+    public void removeListener(final L l) {
         listener.remove(l);
     }
 
     public void fire() {
-        List<L> tmpList = new ArrayList<L>(listener);
-        for (L l : tmpList) {
-            fire(l);
+        if(fireEvents) {
+            List<L> tmpList = new ArrayList<L>(listener);
+            for (L l : tmpList) {
+                fire(l);
+            }
+        } else {
+            eventWasFired = true;
         }
     }
 
+    public void beginAtomic() {
+        assert fireEvents : "endAtomic has to be called before another beginAtomic may be called";
+        this.fireEvents = false;
+        this.eventWasFired = false;
+    }
+
+    public void endAtomic() {
+        assert !fireEvents : "beginAtomic has to be called first";
+        this.fireEvents = true;
+        if(eventWasFired) {
+            fire();
+        }
+    }
+    
     protected abstract void fire(L l);
 }
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/GraphDocument.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/GraphDocument.java	Wed Jul 27 17:32:44 2011 -0700
@@ -55,14 +55,12 @@
     }
 
     public void addGroup(Group group) {
-        group.setDocument(this);
         groups.add(group);
         getChangedEvent().fire();
     }
 
     public void removeGroup(Group group) {
         if (groups.contains(group)) {
-            group.setDocument(null);
             groups.remove(group);
             getChangedEvent().fire();
         }
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Group.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Group.java	Wed Jul 27 17:32:44 2011 -0700
@@ -23,10 +23,6 @@
  */
 package com.sun.hotspot.igv.data;
 
-import com.sun.hotspot.igv.data.ChangedEvent;
-import com.sun.hotspot.igv.data.ChangedEventProvider;
-import com.sun.hotspot.igv.data.Properties;
-import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashSet;
@@ -40,18 +36,26 @@
 public class Group extends Properties.Entity implements ChangedEventProvider<Group> {
 
     private List<InputGraph> graphs;
-    private transient ChangedEvent<Group> changedEvent;
-    private GraphDocument document;
     private InputMethod method;
     private String assembly;
+    private transient ChangedEvent<Group> changedEvent;
+    private transient boolean complete = true;
 
     public Group() {
         graphs = new ArrayList<InputGraph>();
-        init();
+        changedEvent = new ChangedEvent<Group>(this);
+
+        // Ensure that name and type are never null
+        getProperties().setProperty("name", "");
+        getProperties().setProperty("type", "");
     }
 
-    private void init() {
-        changedEvent = new ChangedEvent<Group>(this);
+    public void setComplete(boolean complete) {
+        this.complete = complete;
+    }
+
+    public boolean isComplete() {
+        return complete;
     }
 
     public void fireChangedEvent() {
@@ -74,14 +78,6 @@
         return method;
     }
 
-    void setDocument(GraphDocument document) {
-        this.document = document;
-    }
-
-    public GraphDocument getDocument() {
-        return document;
-    }
-
     public ChangedEvent<Group> getChangedEvent() {
         return changedEvent;
     }
@@ -90,11 +86,15 @@
         return Collections.unmodifiableList(graphs);
     }
 
-    public void addGraph(InputGraph g) {
-        assert g != null;
-        assert !graphs.contains(g);
+    public InputGraph addGraph(String name) {
+        return addGraph(name, null);
+    }
+
+    public InputGraph addGraph(String name, Pair<InputGraph, InputGraph> pair) {
+        InputGraph g = new InputGraph(graphs.size(), this, name, pair);
         graphs.add(g);
         changedEvent.fire();
+        return g;
     }
 
     public void removeGraph(InputGraph g) {
@@ -110,20 +110,10 @@
         for (InputGraph g : graphs) {
             Set<Integer> ids = g.getNodesAsSet();
             result.addAll(g.getNodesAsSet());
-            for (Integer i : ids) {
-                result.add(-i);
-            }
         }
         return result;
     }
 
-    public InputGraph getLastAdded() {
-        if (graphs.size() == 0) {
-            return null;
-        }
-        return graphs.get(graphs.size() - 1);
-    }
-
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
@@ -138,4 +128,8 @@
     public String getName() {
         return getProperties().get("name");
     }
+
+    public String getType() {
+        return getProperties().get("type");
+    }
 }
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBlock.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBlock.java	Wed Jul 27 17:32:44 2011 -0700
@@ -23,10 +23,10 @@
  */
 package com.sun.hotspot.igv.data;
 
-import java.awt.Rectangle;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
 
@@ -37,46 +37,57 @@
 public class InputBlock {
 
     private List<InputNode> nodes;
-    private List<String> successorNames;
     private String name;
     private InputGraph graph;
-    private Rectangle bounds;
     private Set<InputBlock> successors;
-    private Set<InputBlock> predecessors;
-    private Set<InputBlockEdge> inputs;
-    private Set<InputBlockEdge> outputs;
+
+    @Override
+    public int hashCode() {
+        return name.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+
+        if (o == this) {
+            return true;
+        }
 
-    public InputBlock(InputGraph graph, String name) {
+        if (o == null || (!(o instanceof InputBlock))) {
+            return false;
+        }
+        
+        final InputBlock b = (InputBlock)o;
+        final boolean result = b.nodes.equals(nodes) && b.name.equals(name) && b.successors.size() == successors.size();
+        if (!result) {
+            return false;
+        }
+
+        final HashSet<String> s = new HashSet<String>();
+        for (InputBlock succ : successors) {
+            s.add(succ.name);
+        }
+
+        for (InputBlock succ : b.successors) {
+            if (!s.contains(succ.name)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    InputBlock(InputGraph graph, String name) {
         this.graph = graph;
         this.name = name;
         nodes = new ArrayList<InputNode>();
-        successorNames = new ArrayList<String>();
-        successors = new HashSet<InputBlock>();
-        predecessors = new HashSet<InputBlock>();
-        inputs = new HashSet<InputBlockEdge>();
-        outputs = new HashSet<InputBlockEdge>();
-    }
-
-    public void removeSuccessor(InputBlock b) {
-        if (successors.contains(b)) {
-            successors.remove(b);
-            b.predecessors.remove(this);
-            InputBlockEdge e = new InputBlockEdge(this, b);
-            assert outputs.contains(e);
-            outputs.remove(e);
-            assert b.inputs.contains(e);
-            b.inputs.remove(e);
-        }
+        successors = new LinkedHashSet<InputBlock>(2);
     }
 
     public String getName() {
         return name;
     }
 
-    public void setName(String s) {
-        name = s;
-    }
-
     public List<InputNode> getNodes() {
         return Collections.unmodifiableList(nodes);
     }
@@ -85,56 +96,24 @@
         InputNode n = graph.getNode(id);
         assert n != null;
         graph.setBlock(n, this);
-        addNode(graph.getNode(id));
-    }
-
-    public void addNode(InputNode node) {
-        assert !nodes.contains(node);
+        final InputNode node = graph.getNode(id);
+        assert node != null;
+        assert !nodes.contains(node) : "duplicate : " + node;
         nodes.add(node);
     }
 
-    public Set<InputBlock> getPredecessors() {
-        return Collections.unmodifiableSet(predecessors);
-    }
-
     public Set<InputBlock> getSuccessors() {
         return Collections.unmodifiableSet(successors);
     }
 
-    public Set<InputBlockEdge> getInputs() {
-        return Collections.unmodifiableSet(inputs);
-    }
-
-    public Set<InputBlockEdge> getOutputs() {
-        return Collections.unmodifiableSet(outputs);
-    }
-
-    // resolveBlockLinks must be called afterwards
-    public void addSuccessor(String name) {
-        successorNames.add(name);
+    @Override
+    public String toString() {
+        return "Block " + this.getName();
     }
 
-    public void resolveBlockLinks() {
-        for (String s : successorNames) {
-            InputBlock b = graph.getBlock(s);
-            addSuccessor(b);
-        }
-
-        successorNames.clear();
-    }
-
-    public void addSuccessor(InputBlock b) {
+    void addSuccessor(InputBlock b) {
         if (!successors.contains(b)) {
             successors.add(b);
-            b.predecessors.add(this);
-            InputBlockEdge e = new InputBlockEdge(this, b);
-            outputs.add(e);
-            b.inputs.add(e);
         }
     }
-
-    @Override
-    public String toString() {
-        return this.getName();
-    }
 }
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBlockEdge.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBlockEdge.java	Wed Jul 27 17:32:44 2011 -0700
@@ -29,8 +29,15 @@
  */
 public class InputBlockEdge {
 
+    public enum State {
+        SAME,
+        NEW,
+        DELETED
+    }
+
     private InputBlock from;
     private InputBlock to;
+    private State state = State.SAME;
 
     public InputBlockEdge(InputBlock from, InputBlock to) {
         assert from != null;
@@ -47,13 +54,21 @@
         return to;
     }
 
+    public State getState() {
+        return state;
+    }
+
+    public void setState(State state) {
+        this.state = state;
+    }
+
     @Override
     public boolean equals(Object obj) {
-        if (obj instanceof InputBlockEdge && obj != null) {
+        if (obj != null && obj instanceof InputBlockEdge) {
             InputBlockEdge e = (InputBlockEdge) obj;
             return e.from.equals(from) && e.to.equals(to);
         }
-        return super.equals(obj);
+        return false;
     }
 
     @Override
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputEdge.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputEdge.java	Wed Jul 27 17:32:44 2011 -0700
@@ -23,6 +23,8 @@
  */
 package com.sun.hotspot.igv.data;
 
+import java.util.Comparator;
+
 /**
  *
  * @author Thomas Wuerthinger
@@ -35,13 +37,41 @@
         NEW,
         DELETED
     }
+    
+    public static final Comparator<InputEdge> OUTGOING_COMPARATOR = new Comparator<InputEdge>(){
+
+            public int compare(InputEdge o1, InputEdge o2) {
+                if(o1.getFromIndex() == o2.getFromIndex()) {
+                    return o1.getTo() - o2.getTo();
+                }
+                return o1.getFromIndex() - o2.getFromIndex();
+            }
+    };
+    
+    
+    public static final Comparator<InputEdge> INGOING_COMPARATOR = new Comparator<InputEdge>(){
+
+            public int compare(InputEdge o1, InputEdge o2) {
+                if(o1.getToIndex() == o2.getToIndex()) {
+                    return o1.getFrom() - o2.getFrom();
+                }
+                return o1.getToIndex() - o2.getToIndex();
+            }
+    };
+        
     private char toIndex;
+    private char fromIndex;
     private int from;
     private int to;
     private State state;
-
+    
     public InputEdge(char toIndex, int from, int to) {
+        this((char)0, toIndex, from, to);
+    }
+
+    public InputEdge(char fromIndex, char toIndex, int from, int to) {
         this.toIndex = toIndex;
+        this.fromIndex = fromIndex;
         this.from = from;
         this.to = to;
         this.state = State.SAME;
@@ -58,6 +88,10 @@
     public char getToIndex() {
         return toIndex;
     }
+    
+    public char getFromIndex() {
+        return fromIndex;
+    }
 
     public String getName() {
         return "in" + toIndex;
@@ -77,16 +111,16 @@
             return false;
         }
         InputEdge conn2 = (InputEdge) o;
-        return conn2.toIndex == toIndex && conn2.from == from && conn2.to == to;
+        return conn2.fromIndex == fromIndex && conn2.toIndex == toIndex && conn2.from == from && conn2.to == to;
     }
 
     @Override
     public String toString() {
-        return "Edge from " + from + " to " + to + "(" + (int) toIndex + ") ";
+        return "Edge from " + from + " to " + to + "(" + (int) fromIndex + ", " + (int) toIndex + ") ";
     }
 
     @Override
     public int hashCode() {
-        return (from << 20 | to << 8 | toIndex);
+        return (from << 20 | to << 8 | toIndex << 4 | fromIndex);
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputGraph.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputGraph.java	Wed Jul 27 17:32:44 2011 -0700
@@ -26,9 +26,12 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
-import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 /**
@@ -37,51 +40,134 @@
  */
 public class InputGraph extends Properties.Entity {
 
-    private HashMap<Integer, InputNode> nodes;
-    private ArrayList<InputEdge> edges;
+    private Map<Integer, InputNode> nodes;
+    private Set<InputEdge> edges;
     private Group parent;
-    private HashMap<String, InputBlock> blocks;
-    private HashMap<Integer, InputBlock> nodeToBlock;
-    private boolean isDifferenceGraph;
+    private Map<String, InputBlock> blocks;
+    private Set<InputBlockEdge> blockEdges;
+    private Map<Integer, InputBlock> nodeToBlock;
+    private Pair<InputGraph, InputGraph> sourceGraphs;
+    private int parentIndex;
 
-    public InputGraph(Group parent) {
-        this(parent, null);
+    InputGraph(int parentIndex, Group parent, String name, Pair<InputGraph, InputGraph> sourceGraphs) {
+        this.parentIndex = parentIndex;
+        this.parent = parent;
+        this.sourceGraphs = sourceGraphs;
+        setName(name);
+        nodes = new LinkedHashMap<Integer, InputNode>();
+        edges = new LinkedHashSet<InputEdge>();
+        blocks = new LinkedHashMap<String, InputBlock>();
+        blockEdges = new LinkedHashSet<InputBlockEdge>();
+        nodeToBlock = new LinkedHashMap<Integer, InputBlock>();
+    }
+
+    public InputBlockEdge addBlockEdge(InputBlock left, InputBlock right) {
+        InputBlockEdge edge = new InputBlockEdge(left, right);
+        blockEdges.add(edge);
+        left.addSuccessor(right);
+        return edge;
     }
 
-    public InputGraph(Group parent, InputGraph last) {
-        this(parent, last, "");
+    public Pair<InputGraph, InputGraph> getSourceGraphs() {
+        return sourceGraphs;
+    }
+    
+    public List<InputNode> findRootNodes() {
+        List<InputNode> result = new ArrayList<InputNode>();
+        Set<Integer> nonRoot = new HashSet<Integer>();
+        for(InputEdge curEdges : getEdges()) {
+            nonRoot.add(curEdges.getTo());
+        }
+        
+        for(InputNode node : getNodes()) {
+            if(!nonRoot.contains(node.getId())) {
+                result.add(node);
+            }
+        }
+        
+        return result;
+    }
+    
+    public Map<InputNode, List<InputEdge>> findAllOutgoingEdges() {
+        
+        Map<InputNode, List<InputEdge>> result = new HashMap<InputNode, List<InputEdge>>(getNodes().size());
+        for(InputNode n : this.getNodes()) {
+            result.put(n, new ArrayList<InputEdge>());
+        }
+        
+        for(InputEdge e : this.edges) {
+            int from = e.getFrom();
+            InputNode fromNode = this.getNode(from);
+            List<InputEdge> fromList = result.get(fromNode);
+            assert fromList != null;
+            fromList.add(e);
+        }
+        
+        for(InputNode n : this.getNodes()) {
+            List<InputEdge> list = result.get(n);
+            Collections.sort(list, InputEdge.OUTGOING_COMPARATOR);
+        }
+        
+        return result;
+    }
+    
+    public Map<InputNode, List<InputEdge>> findAllIngoingEdges() {
+        
+        Map<InputNode, List<InputEdge>> result = new HashMap<InputNode, List<InputEdge>>(getNodes().size());
+        for(InputNode n : this.getNodes()) {
+            result.put(n, new ArrayList<InputEdge>());
+        }
+        
+        for(InputEdge e : this.edges) {
+            int to = e.getTo();
+            InputNode toNode = this.getNode(to);
+            List<InputEdge> toList = result.get(toNode);
+            assert toList != null;
+            toList.add(e);
+        }
+        
+        for(InputNode n : this.getNodes()) {
+            List<InputEdge> list = result.get(n);
+            Collections.sort(list, InputEdge.INGOING_COMPARATOR);
+        }
+        
+        return result;
+    }
+    
+    public List<InputEdge> findOutgoingEdges(InputNode n) {
+        List<InputEdge> result = new ArrayList<InputEdge>();
+        
+        for(InputEdge e : this.edges) {
+            if(e.getFrom() == n.getId()) {
+                result.add(e);
+            }
+        }
+        
+        Collections.sort(result, InputEdge.OUTGOING_COMPARATOR);
+        
+        return result;
     }
 
-    private void clearBlocks() {
+    public void clearBlocks() {
         blocks.clear();
         nodeToBlock.clear();
     }
-
-    public InputGraph(Group parent, InputGraph last, String name) {
-        this.parent = parent;
-        setName(name);
-        nodes = new HashMap<Integer, InputNode>();
-        edges = new ArrayList<InputEdge>();
-        blocks = new HashMap<String, InputBlock>();
-        nodeToBlock = new HashMap<Integer, InputBlock>();
-        if (last != null) {
-
-            for (InputNode n : last.getNodes()) {
-                addNode(n);
-            }
-
-            for (InputEdge c : last.getEdges()) {
-                addEdge(c);
-            }
+    
+    public void setEdge(int fromIndex, int toIndex, int from, int to) {
+        assert fromIndex == ((char)fromIndex) : "Downcast must be safe";
+        assert toIndex == ((char)toIndex) : "Downcast must be safe";
+        
+        InputEdge edge = new InputEdge((char)fromIndex, (char)toIndex, from, to);
+        if(!this.getEdges().contains(edge)) {
+            this.addEdge(edge);
         }
     }
 
-    public void schedule(Collection<InputBlock> newBlocks) {
-        clearBlocks();
-        InputBlock noBlock = new InputBlock(this, "no block");
+    public void ensureNodesInBlocks() {
+        InputBlock noBlock = null;
         Set<InputNode> scheduledNodes = new HashSet<InputNode>();
 
-        for (InputBlock b : newBlocks) {
+        for (InputBlock b : getBlocks()) {
             for (InputNode n : b.getNodes()) {
                 assert !scheduledNodes.contains(n);
                 scheduledNodes.add(n);
@@ -91,18 +177,11 @@
         for (InputNode n : this.getNodes()) {
             assert nodes.get(n.getId()) == n;
             if (!scheduledNodes.contains(n)) {
+                if (noBlock == null) {
+                    noBlock = this.addBlock("(no block)");
+                }
                 noBlock.addNode(n.getId());
             }
-        }
-
-        if (noBlock.getNodes().size() != 0) {
-            newBlocks.add(noBlock);
-        }
-        for (InputBlock b : newBlocks) {
-            addBlock(b);
-        }
-
-        for (InputNode n : this.getNodes()) {
             assert this.getBlock(n) != null;
         }
     }
@@ -116,47 +195,37 @@
     }
 
     public InputBlock getBlock(InputNode node) {
+        assert nodes.containsKey(node.getId());
+        assert nodes.get(node.getId()).equals(node);
         return getBlock(node.getId());
     }
 
     public InputGraph getNext() {
         List<InputGraph> list = parent.getGraphs();
-        if (!list.contains(this)) {
-            return null;
-        }
-        int index = list.indexOf(this);
-        if (index == list.size() - 1) {
+        if (parentIndex == list.size() - 1) {
             return null;
         } else {
-            return list.get(index + 1);
+            return list.get(parentIndex + 1);
         }
     }
 
     public InputGraph getPrev() {
         List<InputGraph> list = parent.getGraphs();
-        if (!list.contains(this)) {
-            return null;
-        }
-        int index = list.indexOf(this);
-        if (index == 0) {
+        if (parentIndex == 0) {
             return null;
         } else {
-            return list.get(index - 1);
+            return list.get(parentIndex - 1);
         }
     }
 
+    private void setName(String name) {
+        this.getProperties().setProperty("name", name);
+    }
+
     public String getName() {
         return getProperties().get("name");
     }
 
-    public String getAbsoluteName() {
-        String result = getName();
-        if (this.parent != null) {
-            result = parent.getName() + ": " + result;
-        }
-        return result;
-    }
-
     public Collection<InputNode> getNodes() {
         return Collections.unmodifiableCollection(nodes.values());
     }
@@ -182,19 +251,19 @@
     }
 
     public Collection<InputEdge> getEdges() {
-        return Collections.unmodifiableList(edges);
+        return Collections.unmodifiableSet(edges);
     }
 
     public void removeEdge(InputEdge c) {
-        assert edges.contains(c);
-        edges.remove(c);
-        assert !edges.contains(c);
+        boolean removed = edges.remove(c);
+        assert removed;
     }
 
     public void addEdge(InputEdge c) {
-        assert !edges.contains(c);
-        edges.add(c);
-        assert edges.contains(c);
+        // Be tolerant with duplicated edges.
+        if (!edges.contains(c)) {
+            edges.add(c);
+        }
     }
 
     public Group getGroup() {
@@ -214,35 +283,26 @@
             sb.append(c.toString());
             sb.append("\n");
         }
+
+        for (InputBlock b : getBlocks()) {
+            sb.append(b.toString());
+            sb.append("\n");
+        }
+
         return sb.toString();
     }
 
-    public void addBlock(InputBlock b) {
+    public InputBlock addBlock(String name) {
+        final InputBlock b = new InputBlock(this, name);
         blocks.put(b.getName(), b);
-        for (InputNode n : b.getNodes()) {
-            this.nodeToBlock.put(n.getId(), b);
-        }
-    }
-
-    public void resolveBlockLinks() {
-        for (InputBlock b : blocks.values()) {
-            b.resolveBlockLinks();
-        }
-    }
-
-    public void setName(String s) {
-        getProperties().setProperty("name", s);
+        return b;
     }
 
     public InputBlock getBlock(String s) {
         return blocks.get(s);
     }
 
-    public boolean isDifferenceGraph() {
-        return this.isDifferenceGraph;
-    }
-
-    public void setIsDifferenceGraph(boolean b) {
-        isDifferenceGraph = b;
+    public Collection<InputBlockEdge> getBlockEdges() {
+        return Collections.unmodifiableSet(blockEdges);
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputMethod.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputMethod.java	Wed Jul 27 17:32:44 2011 -0700
@@ -23,7 +23,6 @@
  */
 package com.sun.hotspot.igv.data;
 
-import com.sun.hotspot.igv.data.Properties;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -42,6 +41,29 @@
     private Group group;
     private List<InputBytecode> bytecodes;
 
+    @Override
+    public int hashCode() {
+        int result = name.hashCode();
+        result = result * 31 + bci;
+        result = result * 31 + shortName.hashCode();
+        result = result * 31 + inlined.hashCode();
+        result = result * 31 + bytecodes.hashCode();
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == null || (!(o instanceof InputMethod))) {
+            return false;
+        }
+
+        final InputMethod im = (InputMethod)o;
+        return name.equals(im.name) && bci == im.bci && shortName.equals(im.shortName) &&
+               inlined.equals(im.inlined) && bytecodes.equals(im.bytecodes);
+    }
+
+
+
     /** Creates a new instance of InputMethod */
     public InputMethod(Group parent, String name, String shortName, int bci) {
         this.group = parent;
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputNode.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputNode.java	Wed Jul 27 17:32:44 2011 -0700
@@ -23,6 +23,8 @@
  */
 package com.sun.hotspot.igv.data;
 
+import java.util.Comparator;
+
 /**
  *
  * @author Thomas Wuerthinger
@@ -31,6 +33,34 @@
 
     private int id;
 
+    public static final Comparator<InputNode> COMPARATOR = new Comparator<InputNode>() {
+        public int compare(InputNode o1, InputNode o2) {
+            return o1.getId() - o2.getId();
+        }
+    };
+
+    public static Comparator<InputNode> getPropertyComparator(final String propertyName) {
+        return new Comparator<InputNode>() {
+
+            public int compare(InputNode o1, InputNode o2) {
+
+                int i1 = 0;
+                try {
+                    i1 = Integer.parseInt(o1.getProperties().get(propertyName));
+                } catch(NumberFormatException e) {
+                }
+
+                int i2 = 0;
+                try {
+                    i2 = Integer.parseInt(o2.getProperties().get(propertyName));
+                } catch(NumberFormatException e) {
+                }
+
+                return i1 - i2;
+            }
+        };
+    }
+
     public InputNode(InputNode n) {
         super(n);
         setId(n.id);
@@ -55,15 +85,12 @@
             return false;
         }
         InputNode n = (InputNode) o;
-        if (n.id != id) {
-            return false;
-        }
-        return getProperties().equals(n.getProperties());
+        return n.id == id;
     }
 
     @Override
     public int hashCode() {
-        return id;
+        return id * 13;
     }
 
     @Override
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Pair.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Pair.java	Wed Jul 27 17:32:44 2011 -0700
@@ -58,15 +58,30 @@
 
     @Override
     public boolean equals(Object o) {
-        if (!(o instanceof Pair)) {
+        if (o == null || !(o instanceof Pair)) {
             return false;
         }
         Pair obj = (Pair) o;
-        return l.equals(obj.l) && r.equals(obj.r);
+        boolean b1 = (l == obj.l);
+        if (l != null) {
+            b1 = l.equals(obj.l);
+        }
+
+        boolean b2 = (r == obj.r);
+        if (r != null) {
+            b2 = r.equals(obj.r);
+        }
+        
+        return b1 && b2;
     }
 
     @Override
     public int hashCode() {
-        return l.hashCode() * 71 + r.hashCode();
+        return ((l == null) ? 0 : l.hashCode()) * 71 + ((r == null) ? 0 : r.hashCode());
+    }
+
+    @Override
+    public String toString() {
+        return "[" + l + "/" + r + "]";
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Properties.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Properties.java	Wed Jul 27 17:32:44 2011 -0700
@@ -26,11 +26,13 @@
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.Iterator;
 import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
-
+import java.util.regex.PatternSyntaxException;
 
 /**
  *
@@ -58,13 +60,30 @@
                 return false;
             }
         }
+
+        for (Property prop : p) {
+            String value = this.get(prop.getName());
+            if (value == null || !value.equals(prop.getValue())) {
+                return false;
+            }
+        }
+
         return true;
     }
 
     @Override
     public int hashCode() {
         int hash = 5;
-        hash = 83 * hash + (this.map != null ? this.map.hashCode() : 0);
+
+        if (map != null) {
+            for (int i = 0; i < this.map.length; i++) {
+                if (map[i] == null) {
+                    i++;
+                } else {
+                    hash = hash * 83 + map[i].hashCode();
+                }
+            }
+        }
         return hash;
     }
 
@@ -85,7 +104,7 @@
 
     public Properties(Properties p) {
         map = new String[p.map.length];
-        System.arraycopy(map, 0, p.map, 0, p.map.length);
+        System.arraycopy(p.map, 0, map, 0, p.map.length);
     }
 
     public static class Entity implements Provider {
@@ -105,14 +124,6 @@
         }
     }
 
-    private String getProperty(String key) {
-        for (int i = 0; i < map.length; i += 2)
-            if (map[i] != null && map[i].equals(key)) {
-                return map[i + 1];
-            }
-        return null;
-    }
-
     public interface PropertyMatcher {
 
         String getName();
@@ -133,6 +144,9 @@
         }
 
         public boolean match(String p) {
+            if (p == null) {
+                return false;
+            }
             return !matcher.match(p);
         }
     }
@@ -143,6 +157,12 @@
         private String value;
 
         public StringPropertyMatcher(String name, String value) {
+            if (name == null) {
+                throw new IllegalArgumentException("Property name must not be null!");
+            }
+            if (value == null) {
+                throw new IllegalArgumentException("Property value must not be null!");
+            }
             this.name = name;
             this.value = value;
         }
@@ -152,6 +172,9 @@
         }
 
         public boolean match(String p) {
+            if (p == null) {
+                throw new IllegalArgumentException("Property value must not be null!");
+            }
             return p.equals(value);
         }
     }
@@ -160,10 +183,28 @@
 
         private String name;
         private Pattern valuePattern;
-
+        
         public RegexpPropertyMatcher(String name, String value) {
+            this(name, value, 0);
+        }
+
+        public RegexpPropertyMatcher(String name, String value, int flags) {
+
+            if (name == null) {
+                throw new IllegalArgumentException("Property name must not be null!");
+            }
+
+            if (value == null) {
+                throw new IllegalArgumentException("Property value pattern must not be null!");
+            }
+
             this.name = name;
-            valuePattern = Pattern.compile(value);
+
+            try {
+                valuePattern = Pattern.compile(value, flags);
+            } catch (PatternSyntaxException e) {
+                throw new IllegalArgumentException("Bad pattern: " + value);
+            }
         }
 
         public String getName() {
@@ -171,21 +212,26 @@
         }
 
         public boolean match(String p) {
+            if (p == null) {
+                throw new IllegalArgumentException("Property value must not be null!");
+            }
             Matcher m = valuePattern.matcher(p);
             return m.matches();
         }
     }
 
     public Property selectSingle(PropertyMatcher matcher) {
+
+        final String name = matcher.getName();
         String value = null;
         for (int i = 0; i < map.length; i += 2) {
-            if (map[i] != null && matcher.getName().equals(map[i]))  {
+            if (map[i] != null && name.equals(map[i])) {
                 value = map[i + 1];
                 break;
             }
         }
         if (value != null && matcher.match(value)) {
-            return new Property(matcher.getName(), value);
+            return new Property(name, value);
         } else {
             return null;
         }
@@ -198,13 +244,31 @@
 
     @Override
     public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append("[");
+        List<String[]> pairs = new ArrayList<String[]>();
         for (int i = 0; i < map.length; i += 2) {
             if (map[i + 1] != null) {
-                String p = map[i + 1];
-                sb.append(map[i] + " = " + map[i + 1] + "; ");
+                pairs.add(new String[]{map[i], map[i + 1]});
+            }
+        }
+
+        Collections.sort(pairs, new Comparator<String[]>() {
+            public int compare(String[] o1, String[] o2) {
+                assert o1.length == 2;
+                assert o2.length == 2;
+                return o1[0].compareTo(o2[0]);
             }
+        });
+
+        StringBuilder sb = new StringBuilder();
+        sb.append("[");
+        boolean first = true;
+        for (String[] p : pairs) {
+            if (first) {
+                first = false;
+            } else {
+                sb.append(", ");
+            }
+            sb.append(p[0] + "=" + p[1]);
         }
         return sb.append("]").toString();
     }
@@ -217,10 +281,6 @@
             this.objects = objects;
         }
 
-        public T selectSingle(final String name, final String value) {
-            return selectSingle(new StringPropertyMatcher(name, value));
-        }
-
         public T selectSingle(PropertyMatcher matcher) {
 
             for (T t : objects) {
@@ -233,18 +293,16 @@
             return null;
         }
 
-        public List<T> selectMultiple(final String name, final String value) {
-            return selectMultiple(new StringPropertyMatcher(name, value));
-        }
-
         public List<T> selectMultiple(PropertyMatcher matcher) {
             List<T> result = new ArrayList<T>();
+
             for (T t : objects) {
                 Property p = t.getProperties().selectSingle(matcher);
                 if (p != null) {
                     result.add(t);
                 }
             }
+
             return result;
         }
     }
@@ -259,6 +317,7 @@
     }
 
     public void setProperty(String name, String value) {
+
         for (int i = 0; i < map.length; i += 2) {
             if (map[i] != null && map[i].equals(name)) {
                 String p = map[i + 1];
@@ -289,31 +348,20 @@
         map = newMap;
     }
 
-    public  Iterator<Property> getProperties() {
-        return iterator();
-    }
-
     public void add(Properties properties) {
         for (Property p : properties) {
-            add(p);
+            setProperty(p.getName(), p.getValue());
         }
     }
 
-    public void add(Property property) {
-        assert property.getName() != null;
-        assert property.getValue() != null;
-        setProperty(property.getName(), property.getValue());
-    }
-    class PropertiesIterator implements Iterator<Property>, Iterable<Property> {
-        public Iterator<Property> iterator() {
-                return this;
-        }
+    private class PropertiesIterator implements Iterator<Property> {
 
         int index;
 
         public boolean hasNext() {
-            while (index < map.length && map[index + 1] == null)
+            while (index < map.length && map[index + 1] == null) {
                 index += 2;
+            }
             return index < map.length;
         }
 
@@ -328,8 +376,8 @@
         public void remove() {
             throw new UnsupportedOperationException("Not supported yet.");
         }
+    }
 
-    }
     public Iterator<Property> iterator() {
         return new PropertiesIterator();
     }
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Property.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Property.java	Wed Jul 27 17:32:44 2011 -0700
@@ -32,25 +32,20 @@
 public class Property implements Serializable {
 
     public static final long serialVersionUID = 1L;
-
     private String name;
     private String value;
 
-    private Property() {
-        this(null, null);
-    }
-
-    private Property(Property p) {
-        this(p.getName(), p.getValue());
-    }
-
-    private Property(String name) {
-        this(name, null);
-    }
-
-    public Property(String name, String value) {
+    Property(String name, String value) {
         this.name = name;
         this.value = value;
+
+        if (value == null) {
+            throw new IllegalArgumentException("Property value must not be null!");
+        }
+
+        if (name == null) {
+            throw new IllegalArgumentException("Property name must not be null!");
+        }
     }
 
     public String getName() {
@@ -63,17 +58,20 @@
 
     @Override
     public String toString() {
-        return name + " = " + value + "; ";
+        return name + "=" + value;
     }
 
     @Override
     public boolean equals(Object o) {
-        if (!(o instanceof Property)) return false;
-        Property p2 = (Property)o;
+        if (!(o instanceof Property)) {
+            return false;
+        }
+        Property p2 = (Property) o;
         return name.equals(p2.name) && value.equals(p2.value);
     }
+
     @Override
     public int hashCode() {
-        return name.hashCode() + value == null ? 0 : value.hashCode();
+        return name.hashCode() * 13 + value.hashCode();
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Source.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.data;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class Source {
+
+    private List<InputNode> sourceNodes;
+    private Set<Integer> set;
+
+    public Source() {
+        sourceNodes = new ArrayList<InputNode>(1);
+        set = new LinkedHashSet<Integer>(1);
+    }
+
+    public List<InputNode> getSourceNodes() {
+        return Collections.unmodifiableList(sourceNodes);
+    }
+
+    public Set<Integer> getSourceNodesAsSet() {
+        return Collections.unmodifiableSet(set);
+    }
+
+    public void addSourceNode(InputNode n) {
+        if (!set.contains(n.getId())) {
+            sourceNodes.add(n);
+            set.add(n.getId());
+        }
+    }
+
+    public interface Provider {
+
+        public Source getSource();
+    }
+
+    public void addSourceNodes(Source s) {
+        for (InputNode n : s.getSourceNodes()) {
+            addSourceNode(n);
+        }
+    }
+}
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Parser.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Parser.java	Wed Jul 27 17:32:44 2011 -0700
@@ -30,15 +30,17 @@
 import com.sun.hotspot.igv.data.InputGraph;
 import com.sun.hotspot.igv.data.InputMethod;
 import com.sun.hotspot.igv.data.InputNode;
+import com.sun.hotspot.igv.data.Pair;
 import com.sun.hotspot.igv.data.Properties;
-import com.sun.hotspot.igv.data.Property;
 import com.sun.hotspot.igv.data.services.GroupCallback;
 import com.sun.hotspot.igv.data.serialization.XMLParser.ElementHandler;
 import com.sun.hotspot.igv.data.serialization.XMLParser.HandoverElementHandler;
 import com.sun.hotspot.igv.data.serialization.XMLParser.ParseMonitor;
 import com.sun.hotspot.igv.data.serialization.XMLParser.TopElementHandler;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
 import org.xml.sax.XMLReader;
@@ -63,6 +65,7 @@
     public static final String REMOVE_EDGE_ELEMENT = "removeEdge";
     public static final String REMOVE_NODE_ELEMENT = "removeNode";
     public static final String METHOD_NAME_PROPERTY = "name";
+    public static final String GROUP_NAME_PROPERTY = "name";
     public static final String METHOD_IS_PUBLIC_PROPERTY = "public";
     public static final String METHOD_IS_STATIC_PROPERTY = "static";
     public static final String TRUE_VALUE = "true";
@@ -73,7 +76,9 @@
     public static final String TO_PROPERTY = "to";
     public static final String PROPERTY_NAME_PROPERTY = "name";
     public static final String GRAPH_NAME_PROPERTY = "name";
-    public static final String TO_INDEX_PROPERTY = "index";
+    public static final String FROM_INDEX_PROPERTY = "fromIndex";
+    public static final String TO_INDEX_PROPERTY = "toIndex";
+    public static final String TO_INDEX_ALT_PROPERTY = "index";
     public static final String METHOD_ELEMENT = "method";
     public static final String INLINE_ELEMENT = "inline";
     public static final String BYTECODES_ELEMENT = "bytecodes";
@@ -86,10 +91,11 @@
     public static final String SUCCESSOR_ELEMENT = "successor";
     public static final String ASSEMBLY_ELEMENT = "assembly";
     public static final String DIFFERENCE_PROPERTY = "difference";
-    private TopElementHandler xmlDocument = new TopElementHandler();
+    private TopElementHandler<GraphDocument> xmlDocument = new TopElementHandler<GraphDocument>();
     private boolean difference;
     private GroupCallback groupCallback;
     private HashMap<String, Integer> idCache = new HashMap<String, Integer>();
+    private ArrayList<Pair<String, String>> blockConnections = new ArrayList<Pair<String, String>>();
     private int maxId = 0;
 
     private int lookupID(String i) {
@@ -115,11 +121,10 @@
         @Override
         protected Group start() throws SAXException {
             Group group = new Group();
-            Parser.this.difference = false;
+            group.setComplete(false);
+            
             String differenceProperty = this.readAttribute(DIFFERENCE_PROPERTY);
-            if (differenceProperty != null && (differenceProperty.equals("1") || differenceProperty.equals("true"))) {
-                Parser.this.difference = true;
-            }
+            Parser.this.difference = (differenceProperty != null && (differenceProperty.equals("1") || differenceProperty.equals("true")));
 
             ParseMonitor monitor = getMonitor();
             if (monitor != null) {
@@ -131,8 +136,10 @@
 
         @Override
         protected void end(String text) throws SAXException {
+            Group group = getObject();
+            group.setComplete(true);
             if (groupCallback == null) {
-                getParentObject().addGroup(getObject());
+                getParentObject().addGroup(group);
             }
         }
     };
@@ -195,19 +202,72 @@
         protected InputGraph start() throws SAXException {
 
             String name = readAttribute(GRAPH_NAME_PROPERTY);
-            InputGraph previous = getParentObject().getLastAdded();
-            if (!difference) {
-                previous = null;
+            InputGraph curGraph = getParentObject().addGraph(name);
+            if (difference) {
+
+                List<InputGraph> list = getParentObject().getGraphs();
+                if (list.size() > 1) {
+                    InputGraph previous = list.get(list.size() - 2);
+                    for (InputNode n : previous.getNodes()) {
+                        curGraph.addNode(n);
+                    }
+                    for (InputEdge e : previous.getEdges()) {
+                        curGraph.addEdge(e);
+                    }
+                }
             }
-            InputGraph curGraph = new InputGraph(getParentObject(), previous, name);
             this.graph = curGraph;
             return curGraph;
         }
 
         @Override
         protected void end(String text) throws SAXException {
-            getParentObject().addGraph(graph);
-            graph.resolveBlockLinks();
+            // NOTE: Some graphs intentionally don't provide blocks. Instead
+            //       they later generate the blocks from other information such
+            //       as node properties (example: ServerCompilerScheduler).
+            //       Thus, we shouldn't assign nodes that don't belong to any
+            //       block to some artificial block below unless blocks are
+            //       defined and nodes are assigned to them.
+
+            if (graph.getBlocks().size() > 0) {
+                boolean blocksContainNodes = false;
+                for (InputBlock b : graph.getBlocks()) {
+                    if (b.getNodes().size() > 0) {
+                        blocksContainNodes = true;
+                        break;
+                    }
+                }
+
+                if (!blocksContainNodes) {
+                    graph.clearBlocks();
+                    blockConnections.clear();
+                } else {
+                    // Blocks and their nodes defined: add other nodes to an
+                    //  artificial "no block" block
+                    InputBlock noBlock = null;
+                    for (InputNode n : graph.getNodes()) {
+                        if (graph.getBlock(n) == null) {
+                            if (noBlock == null) {
+                                noBlock = graph.addBlock("(no block)");
+                            }
+
+                            noBlock.addNode(n.getId());
+                        }
+
+                        assert graph.getBlock(n) != null;
+                    }
+                }
+            }
+
+            // Resolve block successors
+            for (Pair<String, String> p : blockConnections) {
+                final InputBlock left = graph.getBlock(p.getLeft());
+                assert left != null;
+                final InputBlock right = graph.getBlock(p.getRight());
+                assert right != null;
+                graph.addBlockEdge(left, right);
+            }
+            blockConnections.clear();
         }
     };
     // <nodes>
@@ -221,8 +281,10 @@
         protected InputBlock start() throws SAXException {
             InputGraph graph = getParentObject();
             String name = readRequiredAttribute(BLOCK_NAME_PROPERTY).intern();
-            InputBlock b = new InputBlock(getParentObject(), name);
-            graph.addBlock(b);
+            InputBlock b = graph.addBlock(name);
+            for (InputNode n : b.getNodes()) {
+                assert graph.getBlock(n).equals(b);
+            }
             return b;
         }
     };
@@ -253,7 +315,7 @@
         @Override
         protected InputBlock start() throws SAXException {
             String name = readRequiredAttribute(BLOCK_NAME_PROPERTY);
-            getParentObject().addSuccessor(name);
+            blockConnections.add(new Pair<String, String>(getParentObject().getName(), name));
             return getParentObject();
         }
     };
@@ -301,12 +363,21 @@
 
         @Override
         protected InputEdge start() throws SAXException {
+            int fromIndex = 0;
             int toIndex = 0;
             int from = -1;
             int to = -1;
 
             try {
+                String fromIndexString = readAttribute(FROM_INDEX_PROPERTY);
+                if (fromIndexString != null) {
+                    fromIndex = Integer.parseInt(fromIndexString);
+                }
+
                 String toIndexString = readAttribute(TO_INDEX_PROPERTY);
+                if (toIndexString == null) {
+                    toIndexString = readAttribute(TO_INDEX_ALT_PROPERTY);
+                }
                 if (toIndexString != null) {
                     toIndex = Integer.parseInt(toIndexString);
                 }
@@ -317,8 +388,7 @@
                 throw new SAXException(e);
             }
 
-
-            InputEdge conn = new InputEdge((char) toIndex, from, to);
+            InputEdge conn = new InputEdge((char) fromIndex, (char) toIndex, from, to);
             return start(conn);
         }
 
@@ -362,7 +432,7 @@
         @Override
         public String start() throws SAXException {
             return readRequiredAttribute(PROPERTY_NAME_PROPERTY).intern();
-        }
+         }
 
         @Override
         public void end(String text) {
@@ -420,7 +490,7 @@
     }
 
     // Returns a new GraphDocument object deserialized from an XML input source.
-    public GraphDocument parse(XMLReader reader, InputSource source, XMLParser.ParseMonitor monitor) throws SAXException {
+    public synchronized GraphDocument parse(XMLReader reader, InputSource source, XMLParser.ParseMonitor monitor) throws SAXException {
         reader.setContentHandler(new XMLParser(xmlDocument, monitor));
         try {
             reader.parse(source);
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Printer.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Printer.java	Wed Jul 27 17:32:44 2011 -0700
@@ -34,6 +34,7 @@
 import com.sun.hotspot.igv.data.Properties;
 import com.sun.hotspot.igv.data.Property;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.Writer;
 import java.util.HashSet;
 import java.util.Set;
@@ -44,6 +45,16 @@
  */
 public class Printer {
 
+    private InputStream in;
+
+    public Printer() {
+        this(null);
+    }
+
+    public Printer(InputStream inputStream) {
+        this.in = inputStream;
+    }
+
     public void export(Writer writer, GraphDocument document) {
 
         XMLWriter xmlWriter = new XMLWriter(writer);
@@ -71,14 +82,24 @@
         writer.startTag(Parser.GROUP_ELEMENT, attributes);
         writer.writeProperties(g.getProperties());
 
-        if (g.getMethod() != null) {
-            export(writer, g.getMethod());
+        boolean shouldExport = true;
+        if (in != null) {
+            char c = (char) in.read();
+            if (c != 'y') {
+                shouldExport = false;
+            }
         }
 
-        InputGraph previous = null;
-        for (InputGraph graph : g.getGraphs()) {
-            export(writer, graph, previous, true);
-            previous = graph;
+        if (shouldExport) {
+            if (g.getMethod() != null) {
+                export(writer, g.getMethod());
+            }
+
+            InputGraph previous = null;
+            for (InputGraph graph : g.getGraphs()) {
+                export(writer, graph, previous, true);
+                previous = graph;
+            }
         }
 
         writer.endTag();
@@ -153,23 +174,25 @@
 
         writer.startTag(Parser.CONTROL_FLOW_ELEMENT);
         for (InputBlock b : graph.getBlocks()) {
-
             writer.startTag(Parser.BLOCK_ELEMENT, new Properties(Parser.BLOCK_NAME_PROPERTY, b.getName()));
-
-            writer.startTag(Parser.SUCCESSORS_ELEMENT);
-            for (InputBlock s : b.getSuccessors()) {
-                writer.simpleTag(Parser.SUCCESSOR_ELEMENT, new Properties(Parser.BLOCK_NAME_PROPERTY, s.getName()));
+            
+            if (b.getSuccessors().size() > 0) {
+                writer.startTag(Parser.SUCCESSORS_ELEMENT);
+                for (InputBlock s : b.getSuccessors()) {
+                    writer.simpleTag(Parser.SUCCESSOR_ELEMENT, new Properties(Parser.BLOCK_NAME_PROPERTY, s.getName()));
+                }
+                writer.endTag();
             }
-            writer.endTag();
 
+            if (b.getNodes().size() > 0) {
             writer.startTag(Parser.NODES_ELEMENT);
-            for (InputNode n : b.getNodes()) {
-                writer.simpleTag(Parser.NODE_ELEMENT, new Properties(Parser.NODE_ID_PROPERTY, n.getId() + ""));
+                for (InputNode n : b.getNodes()) {
+                    writer.simpleTag(Parser.NODE_ELEMENT, new Properties(Parser.NODE_ID_PROPERTY, n.getId() + ""));
+                }
+                writer.endTag();
             }
+            
             writer.endTag();
-
-            writer.endTag();
-
         }
 
         writer.endTag();
@@ -199,8 +222,8 @@
             b.append(" ");
             b.append(code.getName());
             b.append("\n");
-
         }
+        
         b.append("]]>");
         w.write(b.toString());
         w.endTag();
@@ -209,7 +232,12 @@
 
     private Properties createProperties(InputEdge edge) {
         Properties p = new Properties();
-        p.setProperty(Parser.TO_INDEX_PROPERTY, Integer.toString(edge.getToIndex()));
+        if (edge.getToIndex() != 0) {
+            p.setProperty(Parser.TO_INDEX_PROPERTY, Integer.toString(edge.getToIndex()));
+        }
+        if (edge.getFromIndex() != 0) {
+            p.setProperty(Parser.FROM_INDEX_PROPERTY, Integer.toString(edge.getFromIndex()));
+        }
         p.setProperty(Parser.TO_PROPERTY, Integer.toString(edge.getTo()));
         p.setProperty(Parser.FROM_PROPERTY, Integer.toString(edge.getFrom()));
         return p;
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLParser.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLParser.java	Wed Jul 27 17:32:44 2011 -0700
@@ -23,7 +23,6 @@
  */
 package com.sun.hotspot.igv.data.serialization;
 
-import com.sun.hotspot.igv.data.Property;
 import com.sun.hotspot.igv.data.Properties;
 import java.util.HashMap;
 import java.util.Stack;
@@ -209,9 +208,10 @@
     public void endPrefixMapping(String prefix) throws SAXException {
     }
 
+    @SuppressWarnings("unchecked")
     public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
+        assert !stack.isEmpty();
 
-        assert !stack.isEmpty();
         ElementHandler parent = stack.peek();
         if (parent != null) {
             ElementHandler child = parent.getChild(qName);
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLWriter.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLWriter.java	Wed Jul 27 17:32:44 2011 -0700
@@ -111,7 +111,7 @@
     }
 
     public void writeProperties(Properties props) throws IOException {
-        if (props.getProperties().hasNext() == false) {
+        if (props.iterator().hasNext() == false) {
             return;
         }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/ChangedEventTest.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package com.sun.hotspot.igv.data;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class ChangedEventTest {
+
+    public ChangedEventTest() {
+    }
+
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+    }
+
+    @AfterClass
+    public static void tearDownClass() throws Exception {
+    }
+
+    @Before
+    public void setUp() {
+    }
+
+    @After
+    public void tearDown() {
+    }
+
+    /**
+     * Test of addListener method, of class Event.
+     */
+    @Test
+    public void testBase() {
+
+        ChangedEvent<Integer> e = new ChangedEvent<Integer>(5);
+        final int[] fireCount = new int[1];
+
+        e.addListener(new ChangedListener<Integer>() {
+            public void changed(Integer s) {
+                assertEquals(s.intValue(), 5);
+                fireCount[0]++;
+            }
+        });
+
+        e.fire();
+        assertEquals(1, fireCount[0]);
+
+        e.fire();
+        assertEquals(2, fireCount[0]);
+
+        e.beginAtomic();
+
+        e.fire();
+        assertEquals(2, fireCount[0]);
+
+        e.fire();
+        assertEquals(2, fireCount[0]);
+
+        e.fire();
+        assertEquals(2, fireCount[0]);
+
+        e.endAtomic();
+        assertEquals(3, fireCount[0]);
+
+    }
+
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/ControllableChangedListenerTest.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package com.sun.hotspot.igv.data;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class ControllableChangedListenerTest {
+
+    public ControllableChangedListenerTest() {
+    }
+
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+    }
+
+    @AfterClass
+    public static void tearDownClass() throws Exception {
+    }
+
+    @Before
+    public void setUp() {
+    }
+
+    @After
+    public void tearDown() {
+    }
+
+    /**
+     * Test of isEnabled method, of class ControllableChangedListener.
+     */
+    @Test
+    public void testBase() {
+
+        final boolean[] hasFired = new boolean[1];
+        final boolean[] shouldFire = new boolean[1];
+        final Integer[] valueToFire = new Integer[1];
+        ControllableChangedListener<Integer> l = new ControllableChangedListener<Integer>() {
+
+            @Override
+            public void filteredChanged(Integer value) {
+                assertTrue(shouldFire[0]);
+                assertEquals(valueToFire[0], value);
+                hasFired[0] = true;
+            }
+        };
+
+        shouldFire[0] = true;
+        valueToFire[0] = 1;
+        hasFired[0] = false;
+        l.changed(1);
+        assertTrue(hasFired[0]);
+
+        shouldFire[0] = false;
+        hasFired[0] = false;
+        l.setEnabled(false);
+        l.changed(1);
+        assertFalse(hasFired[0]);
+
+        shouldFire[0] = true;
+        valueToFire[0] = 1;
+        hasFired[0] = false;
+        l.setEnabled(true);
+        l.changed(1);
+        assertTrue(hasFired[0]);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/GroupTest.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package com.sun.hotspot.igv.data;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class GroupTest {
+
+    public GroupTest() {
+    }
+
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+
+    }
+
+    @AfterClass
+    public static void tearDownClass() throws Exception {
+    }
+
+    @Before
+    public void setUp() {
+    }
+
+    @After
+    public void tearDown() {
+    }
+
+    /**
+     * Test of getAllNodes method, of class Group.
+     */
+    @Test
+    public void testGetAllNodes() {
+        final Group g = new Group();
+        final InputGraph graph1 = g.addGraph("1");
+        final InputGraph graph2 = g.addGraph("2");
+        graph1.addNode(new InputNode(1));
+        graph1.addNode(new InputNode(2));
+        graph2.addNode(new InputNode(2));
+        graph2.addNode(new InputNode(3));
+        assertEquals(g.getAllNodes(), new HashSet(Arrays.asList(1, 2, 3)));
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/InputGraphTest.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package com.sun.hotspot.igv.data;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class InputGraphTest {
+
+    /**
+     *    1
+     *   / \
+     *  2   3
+     *   \  |  5
+     *    \ | /
+     *      4
+     */
+    private static InputGraph referenceGraph;
+
+    private static InputGraph emptyGraph;
+
+    private static final InputNode N1 = new InputNode(1);
+    private static final InputNode N2 = new InputNode(2);
+    private static final InputNode N3 = new InputNode(3);
+    private static final InputNode N4 = new InputNode(4);
+    private static final InputNode N5 = new InputNode(5);
+    private static final InputEdge E12 = new InputEdge((char)0, 1, 2);
+    private static final InputEdge E13 = new InputEdge((char)0, 1, 3);
+    private static final InputEdge E24 = new InputEdge((char)0, 2, 4);
+    private static final InputEdge E34 = new InputEdge((char)0, 3, 4);
+    private static final InputEdge E54 = new InputEdge((char)0, 5, 4);
+
+    public InputGraphTest() {
+    }
+
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+        Group group = new Group();
+
+        emptyGraph = group.addGraph("emptyGraph");
+
+        referenceGraph = group.addGraph("referenceGraph");
+        referenceGraph.addNode(N1);
+        referenceGraph.addNode(N2);
+        referenceGraph.addNode(N3);
+        referenceGraph.addNode(N4);
+        referenceGraph.addNode(N5);
+
+        referenceGraph.addEdge(E12);
+        referenceGraph.addEdge(E13);
+        referenceGraph.addEdge(E24);
+        referenceGraph.addEdge(E34);
+        referenceGraph.addEdge(E54);
+    }
+
+    @AfterClass
+    public static void tearDownClass() throws Exception {
+    }
+
+    @Before
+    public void setUp() {
+    }
+
+    @After
+    public void tearDown() {
+    }
+
+    /**
+     * Test of equals method, of class InputGraph.
+     */
+    @Test
+    public void testEquals() {
+
+        Group parentA = new Group();
+        InputGraph a = parentA.addGraph("graph");
+
+        Group parentB = new Group();
+        InputGraph b = parentB.addGraph("graph");
+
+        InputGraph c = parentB.addGraph("graph");
+
+        Util.assertGraphEquals(a, b);
+        Util.assertGraphEquals(b, c);
+
+        a.addNode(new InputNode(1));
+        Util.assertGraphNotEquals(a, b);
+
+        b.addNode(new InputNode(1));
+        Util.assertGraphEquals(a, b);
+    }
+
+    /**
+     * Test of findRootNodes method, of class InputGraph.
+     */
+    @Test
+    public void testFindRootNodes() {
+        assertTrue(emptyGraph.findRootNodes().size() == 0);
+
+        List<InputNode> result = referenceGraph.findRootNodes();
+        assertTrue(result.size() == 2);
+        assertTrue(result.contains(N1));
+        assertTrue(result.contains(N5));
+    }
+
+    /**
+     * Test of findAllOutgoingEdges method, of class InputGraph.
+     */
+    @Test
+    public void testFindAllOutgoingEdges() {
+        assertTrue(emptyGraph.findAllOutgoingEdges().size() == 0);
+
+        Map<InputNode, List<InputEdge>> result = referenceGraph.findAllOutgoingEdges();
+        assertTrue(result.size() == 5);
+        assertEquals(result.get(N1), Arrays.asList(E12, E13));
+        assertEquals(result.get(N2), Arrays.asList(E24));
+        assertEquals(result.get(N3), Arrays.asList(E34));
+        assertEquals(result.get(N4), Arrays.asList());
+        assertEquals(result.get(N5), Arrays.asList(E54));
+    }
+
+    /**
+     * Test of findAllIngoingEdges method, of class InputGraph.
+     */
+    @Test
+    public void testFindAllIngoingEdges() {
+        assertTrue(emptyGraph.findAllIngoingEdges().size() == 0);
+
+        Map<InputNode, List<InputEdge>> result = referenceGraph.findAllIngoingEdges();
+        assertTrue(result.size() == 5);
+        assertEquals(result.get(N1), Arrays.asList());
+        assertEquals(result.get(N2), Arrays.asList(E12));
+        assertEquals(result.get(N3), Arrays.asList(E13));
+        assertEquals(result.get(N4), Arrays.asList(E24, E34, E54));
+        assertEquals(result.get(N5), Arrays.asList());
+    }
+
+    /**
+     * Test of findOutgoingEdges method, of class InputGraph.
+     */
+    @Test
+    public void testFindOutgoingEdges() {
+        assertTrue(emptyGraph.findOutgoingEdges(new InputNode(1)).size() == 0);
+
+        assertEquals(referenceGraph.findOutgoingEdges(N1), Arrays.asList(E12, E13));
+        assertEquals(referenceGraph.findOutgoingEdges(N2), Arrays.asList(E24));
+        assertEquals(referenceGraph.findOutgoingEdges(N3), Arrays.asList(E34));
+        assertEquals(referenceGraph.findOutgoingEdges(N4), Arrays.asList());
+        assertEquals(referenceGraph.findOutgoingEdges(N5), Arrays.asList(E54));
+    }
+
+    /**
+     * Test of getNext method, of class InputGraph.
+     */
+    @Test
+    public void testGetNextPrev() {
+        final Group group = new Group();
+
+        final InputGraph a = group.addGraph("a");
+
+        final InputGraph b = group.addGraph("b");
+
+        final InputGraph c = group.addGraph("c");
+
+        assertEquals(null, a.getPrev());
+        assertEquals(b, a.getNext());
+
+        assertEquals(a, b.getPrev());
+        assertEquals(c, b.getNext());
+
+        assertEquals(b, c.getPrev());
+        assertEquals(null, c.getNext());
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/InputMethodTest.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,96 @@
+/*
+ * 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.sun.hotspot.igv.data;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author Thomas
+ */
+public class InputMethodTest {
+
+    public InputMethodTest() {
+    }
+
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+    }
+
+    @AfterClass
+    public static void tearDownClass() throws Exception {
+    }
+
+    @Before
+    public void setUp() {
+    }
+
+    @After
+    public void tearDown() {
+    }
+
+
+    /**
+     * Test of getBytecodes method, of class InputMethod.
+     */
+    @Test
+    public void testGetSetBytecodes() {
+
+        final String input = "0 iload_0\n" +
+                             "1 iconst_1\n" +
+                             "2 if_icmpne 7\n" +
+                             "5 iconst_1\n" +
+                             "6 ireturn\n" +
+                             "7 iconst_0\n" +
+                             "8 ireturn";
+
+        final Group g = new Group();
+        InputMethod m = new InputMethod(g, "name", "shortName", -1);
+        m.setBytecodes(input);
+
+        assertThat(m.getBytecodes().size(), is(7));
+
+        assertThat(m.getBytecodes().get(0).getBci(), is(0));
+        assertThat(m.getBytecodes().get(1).getBci(), is(1));
+        assertThat(m.getBytecodes().get(2).getBci(), is(2));
+        assertThat(m.getBytecodes().get(3).getBci(), is(5));
+
+        assertThat(m.getBytecodes().get(0).getName(), is("iload_0"));
+        assertThat(m.getBytecodes().get(1).getName(), is("iconst_1"));
+        assertThat(m.getBytecodes().get(2).getName(), is("if_icmpne 7"));
+        assertThat(m.getBytecodes().get(6).getName(), is("ireturn"));
+
+        assertThat(m.getBytecodes().get(2).getInlined(), nullValue());
+        assertThat(m.getBytecodes().get(6).getInlined(), nullValue());
+    }
+
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/PairTest.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.sun.hotspot.igv.data;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class PairTest {
+
+    public PairTest() {
+    }
+
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+    }
+
+    @AfterClass
+    public static void tearDownClass() throws Exception {
+    }
+
+    @Before
+    public void setUp() {
+    }
+
+    @After
+    public void tearDown() {
+    }
+
+    /**
+     * Test of getLeft method, of class Pair.
+     */
+    @Test
+    public void testBase() {
+        Pair p = new Pair();
+        assertTrue(p.getLeft() == null);
+        assertTrue(p.getRight() == null);
+        assertEquals("[null/null]", p.toString());
+        assertFalse(p.equals(null));
+
+        Pair<Integer, Integer> p2 = new Pair(1, 2);
+        assertTrue(p2.getLeft().intValue() == 1);
+        assertTrue(p2.getRight().intValue() == 2);
+        assertFalse(p.equals(p2));
+        assertFalse(p2.equals(p));
+        assertFalse(p.hashCode() == p2.hashCode());
+        assertEquals("[1/2]", p2.toString());
+
+        Pair p3 = new Pair(1, 2);
+        assertTrue(p2.equals(p3));
+        assertTrue(p2.hashCode() == p3.hashCode());
+
+        p2.setLeft(2);
+        assertFalse(p2.equals(p3));
+        assertTrue(p2.getLeft().intValue() == 2);
+        assertTrue(p2.getRight().intValue() == 2);
+        assertFalse(p2.hashCode() == p3.hashCode());
+        assertEquals("[2/2]", p2.toString());
+
+        p2.setRight(1);
+        assertFalse(p2.equals(p3));
+        assertTrue(p2.getLeft().intValue() == 2);
+        assertTrue(p2.getRight().intValue() == 1);
+        assertFalse(p2.hashCode() == p3.hashCode());
+        assertEquals("[2/1]", p2.toString());
+
+        p3.setLeft(2);
+        p3.setRight(1);
+        assertTrue(p2.hashCode() == p3.hashCode());
+        assertTrue(p2.equals(p3));
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/PropertiesTest.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,397 @@
+/*
+ * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.sun.hotspot.igv.data;
+
+import com.sun.hotspot.igv.data.Properties.InvertPropertyMatcher;
+import com.sun.hotspot.igv.data.Properties.PropertyMatcher;
+import com.sun.hotspot.igv.data.Properties.PropertySelector;
+import com.sun.hotspot.igv.data.Properties.RegexpPropertyMatcher;
+import com.sun.hotspot.igv.data.Properties.StringPropertyMatcher;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import junit.framework.TestCase;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class PropertiesTest extends TestCase {
+
+
+    
+    public PropertiesTest(String testName) {
+        super(testName);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    /**
+     * Test of equals method, of class Properties.
+     */
+    public void testEquals() {
+        Properties a = new Properties();
+        assertFalse(a.equals(null));
+        assertTrue(a.equals(a));
+        
+        Properties b = new Properties();
+        assertTrue(a.equals(b));
+        assertTrue(a.hashCode() == b.hashCode());
+
+        a.setProperty("p1", "1");
+        assertFalse(a.equals(b));
+        assertFalse(b.equals(a));
+        assertFalse(a.hashCode() == b.hashCode());
+
+        b.setProperty("p1", "1");
+        assertTrue(a.equals(b));
+        assertTrue(a.hashCode() == b.hashCode());
+
+        Properties c = new Properties(a);
+        assertTrue(c.equals(a));
+        assertTrue(c.equals(b));
+
+        c.setProperty("p1", "2");
+        assertFalse(c.equals(b));
+        assertFalse(c.hashCode() == b.hashCode());
+        assertFalse(c.equals(a));
+        assertFalse(c.hashCode() == a.hashCode());
+
+        a.setProperty("p2", "2");
+        Properties d = new Properties();
+        d.setProperty("p2", "2");
+        d.setProperty("p1", "1");
+        assertTrue(d.equals(a));
+    }
+
+    /**
+     * Test of selectSingle method, of class Properties.
+     */
+    public void testSelectSingle() {
+        
+        final boolean[] called = new boolean[1];
+        final String v = "2";
+        final String n = "p2";
+        
+        PropertyMatcher matcher = new PropertyMatcher() {
+
+            public String getName() {
+                assertFalse(called[0]);
+                called[0] = true;
+                return n;
+            }
+
+            public boolean match(String value) {
+                assertTrue(v.equals(value));
+                return true;
+            }
+        };
+
+        Properties instance = new Properties();
+        instance.setProperty("p1", "1");
+        instance.setProperty(n, v);
+        instance.setProperty("p3", "3");
+        Property result = instance.selectSingle(matcher);
+        assertEquals(result, new Property(n, v));
+
+
+        called[0] = false;
+        PropertyMatcher matcher2 = new PropertyMatcher() {
+
+            public String getName() {
+                assertFalse(called[0]);
+                called[0] = true;
+                return n;
+            }
+
+            public boolean match(String value) {
+                return false;
+            }
+        };
+
+
+        Property result2 = instance.selectSingle(matcher2);
+        assertTrue(result2 == null);
+    }
+
+    /**
+     * Test of get method, of class Properties.
+     */
+    public void testGet() {
+        Properties instance = new Properties();
+        instance.setProperty("p1", "1");
+        assertEquals("1", instance.get("p1"));
+        assertEquals(null, instance.get("p2"));
+    }
+
+    /**
+     * Test of getProperties method, of class Properties.
+     */
+    public void testIterator() {
+        Properties instance = new Properties();
+        instance.setProperty("p1", "1");
+        instance.setProperty("p2", "2");
+        Iterator<Property> result = instance.iterator();
+        assertTrue(result.hasNext());
+        assertEquals(new Property("p1", "1"), result.next());
+        assertTrue(result.hasNext());
+        assertEquals(new Property("p2", "2"), result.next());
+        assertFalse(result.hasNext());
+        assertTrue(result.next() == null);
+
+        try {
+            result.remove();
+            fail();
+        } catch(UnsupportedOperationException e) {}
+    }
+
+    /**
+     * Test of add method, of class Properties.
+     */
+    public void testAdd() {
+        Properties a = new Properties();
+        a.setProperty("p1", "1");
+        a.setProperty("p2", "2");
+
+        Properties b = new Properties();
+        b.setProperty("p1", "1");
+
+        Properties c = new Properties();
+        c.setProperty("p2", "2");
+
+        assertFalse(a.equals(b));
+        b.add(c);
+
+        assertTrue(a.equals(b));
+        
+        b.setProperty("p3", null);
+        assertTrue(a.equals(b));
+    
+        Properties empty = new Properties();
+        b.add(empty);
+        assertTrue(a.equals(b));
+        
+        empty.add(b);
+        assertTrue(a.equals(empty));
+    }
+
+
+    /**
+     * Test the multiple argument constructors.
+     */
+    public void testConstructors() {
+        Properties a = new Properties("p1", "1", "p2", "2", "p3", "3");
+        Properties b = new Properties("p1", "1", "p2", "2");
+        Properties c = new Properties("p1", "1");
+
+        assertTrue(a.get("p3").equals("3"));
+        assertTrue(b.get("p2").equals("2"));
+        assertTrue(b.get("p1").equals("1"));
+
+        b.setProperty("p3", "3");
+        c.setProperty("p2", "2");
+        c.setProperty("p3", "3");
+
+        assertTrue(a.equals(b));
+        assertTrue(a.equals(c));
+    }
+
+    /**
+     * Test Entity class
+     */
+    public void testEntity() {
+
+        Properties p = new Properties();
+
+        Properties.Entity entity = new Properties.Entity();
+        assertEquals(entity.getProperties(), p);
+
+        entity.getProperties().setProperty("p1", "1");
+        Properties.Entity entity2 = new Properties.Entity(entity);
+        assertEquals(entity.getProperties(), entity2.getProperties());
+    }
+
+    /**
+     * Test property selector
+     */
+    public void testPropertySelector() {
+        final Collection<Properties.Entity> c = new ArrayList<Properties.Entity>();
+
+        final Properties.Entity e1 = new Properties.Entity();
+        e1.getProperties().setProperty("p1", "1");
+        e1.getProperties().setProperty("p2", "2");
+        c.add(e1);
+
+        final Properties.Entity e2 = new Properties.Entity();
+        e2.getProperties().setProperty("p2", "2");
+        e2.getProperties().setProperty("p1", "1");
+        e2.getProperties().setProperty("p3", "3");
+        c.add(e2);
+
+        final Properties.Entity e3 = new Properties.Entity();
+        e3.getProperties().setProperty("p3", "3");
+        e3.getProperties().setProperty("p4", "4");
+        c.add(e3);
+
+        final PropertySelector<Properties.Entity> sel = new PropertySelector<Properties.Entity>(c);
+
+        final StringPropertyMatcher matcher1 = new StringPropertyMatcher("p2", "2");
+        assertTrue(sel.selectMultiple(matcher1).size() == 2);
+        assertTrue(sel.selectMultiple(matcher1).contains(e1));
+        assertTrue(sel.selectMultiple(matcher1).contains(e2));
+        assertTrue(sel.selectSingle(matcher1).equals(e1) || sel.selectSingle(matcher1).equals(e2));
+
+        final StringPropertyMatcher matcher2 = new StringPropertyMatcher("p3", "3");
+        assertTrue(sel.selectMultiple(matcher2).size() == 2);
+        assertTrue(sel.selectMultiple(matcher2).contains(e2));
+        assertTrue(sel.selectMultiple(matcher2).contains(e3));
+        assertTrue(sel.selectSingle(matcher2).equals(e2) || sel.selectSingle(matcher2).equals(e3));
+
+        final StringPropertyMatcher matcher3 = new StringPropertyMatcher("p4", "4");
+        assertTrue(sel.selectMultiple(matcher3).size() == 1);
+        assertTrue(sel.selectMultiple(matcher3).contains(e3));
+        assertTrue(sel.selectSingle(matcher3).equals(e3));
+
+        final StringPropertyMatcher matcher4 = new StringPropertyMatcher("p5", "5");
+        assertTrue(sel.selectMultiple(matcher4).size() == 0);
+        assertTrue(sel.selectSingle(matcher4) == null);
+    }
+
+    public void testRemoveProperty() {
+        final Properties p = new Properties();
+        p.setProperty("p1", "1");
+        p.setProperty("p2", "2");
+
+        assertTrue(p.get("p1").equals("1"));
+        assertTrue(p.get("p2").equals("2"));
+
+        p.setProperty("p1", null);
+        assertTrue(p.get("p1") == null);
+        assertTrue(p.get("p2").equals("2"));
+
+        p.setProperty("p2", null);
+        assertTrue(p.get("p1") == null);
+        assertTrue(p.get("p2") == null);
+
+        p.setProperty("p3", "3");
+        assertTrue(p.get("p1") == null);
+        assertTrue(p.get("p2") == null);
+        assertTrue(p.get("p3").equals("3"));
+    }
+
+    /**
+     * Test property matchers
+     */
+    public void testPropertyMatchers() {
+        final StringPropertyMatcher matcher = new StringPropertyMatcher("p1", "1");
+        assertTrue(matcher.getName().equals("p1"));
+        assertTrue(matcher.match("1"));
+        assertFalse(matcher.match("2"));
+        try {
+            matcher.match(null);
+            fail();
+        } catch(IllegalArgumentException e) {}
+
+        try {
+            new StringPropertyMatcher(null, "**");
+            fail();
+        } catch(IllegalArgumentException e) {}
+
+        try {
+            new StringPropertyMatcher("p1", null);
+            fail();
+        } catch(IllegalArgumentException e) {}
+
+        final RegexpPropertyMatcher matcher2 = new RegexpPropertyMatcher("p1", "C.*");
+        assertTrue(matcher2.getName().equals("p1"));
+        assertTrue(matcher2.match("C"));
+        assertTrue(matcher2.match("Casdf"));
+        assertFalse(matcher2.match(" C"));
+        assertFalse(matcher2.match("c"));
+        assertFalse(matcher2.match("asdfC"));
+        
+        try {
+            matcher2.match(null);
+            fail();
+        } catch(IllegalArgumentException e) {}
+
+        try {
+            new RegexpPropertyMatcher("p1", "**");
+            fail();
+        } catch(IllegalArgumentException e) {}
+
+        try {
+            new RegexpPropertyMatcher(null, "1");
+            fail();
+        } catch(IllegalArgumentException e) {}
+
+        try {
+            new RegexpPropertyMatcher("p1", null);
+            fail();
+        } catch(IllegalArgumentException e) {}
+        
+        final InvertPropertyMatcher matcher3 = new InvertPropertyMatcher(matcher);
+        assertTrue(matcher3.getName().equals("p1"));
+        assertFalse(matcher3.match("1"));
+        assertTrue(matcher3.match("2"));
+        assertFalse(matcher3.match(null));
+    }
+
+    public void testToString() {
+        Properties p = new Properties();
+        assertEquals(p.toString(), "[]");
+
+        p.setProperty("p1", "1");
+        assertEquals(p.toString(), "[p1=1]");
+
+        Properties p2 = new Properties();
+        p2.setProperty("p1", "1");
+        p2.setProperty("p2", "2");
+        assertEquals(p2.toString(), "[p1=1, p2=2]");
+
+        Properties p3 = new Properties();
+        p3.setProperty("p2", "2");
+        p3.setProperty("p1", "1");
+        assertEquals(p3.toString(), "[p1=1, p2=2]");
+        
+        p3.setProperty("p0", "0");
+        assertEquals(p3.toString(), "[p0=0, p1=1, p2=2]");
+
+        p2.setProperty("p1", null);
+        assertEquals(p2.toString(), "[p2=2]");
+
+        p2.setProperty("p2", null);
+        assertEquals(p2.toString(), "[]");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/PropertyTest.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.sun.hotspot.igv.data;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class PropertyTest {
+
+    public PropertyTest() {
+    }
+
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+    }
+
+    @AfterClass
+    public static void tearDownClass() throws Exception {
+    }
+
+    @Before
+    public void setUp() {
+    }
+
+    @After
+    public void tearDown() {
+    }
+
+    /**
+     * Test of getName method, of class Property.
+     */
+    @Test
+    public void testGetNameAndValue() {
+        final Property p = new Property("name", "value");
+        assertEquals(p.getName(), "name");
+        assertEquals(p.getValue(), "value");
+
+        try {
+            new Property(null, "value");
+            fail();
+        } catch(IllegalArgumentException e) {
+        }
+
+
+        try {
+            new Property("name", null);
+            fail();
+        } catch(IllegalArgumentException e) {
+        }
+    }
+
+    /**
+     * Test of toString method, of class Property.
+     */
+    @Test
+    public void testToString() {
+        final Property p = new Property("name", "value");
+        assertEquals(p.toString(), "name=value");
+    }
+
+    /**
+     * Test of equals method, of class Property.
+     */
+    @Test
+    public void testEquals() {
+        final Property p = new Property("name", "value");
+        final Object o = new Object();
+        assertFalse(p.equals(o));
+        assertFalse(p.equals(null));
+        assertTrue(p.equals(p));
+
+        final Property p2 = new Property("name", "value1");
+        assertFalse(p.equals(p2));
+        assertTrue(p.hashCode() != p2.hashCode());
+
+        final Property p3 = new Property("name2", "value");
+        assertFalse(p.equals(p3));
+        assertTrue(p.hashCode() != p3.hashCode());
+        assertTrue(p2.hashCode() != p3.hashCode());
+
+        final Property p4 = new Property("name", "value");
+        assertEquals(p, p4);
+        assertEquals(p.hashCode(), p4.hashCode());
+    
+        final Property p5 = new Property("value", "name");
+        assertFalse(p.equals(p5));
+        assertTrue(p.hashCode() != p5.hashCode());
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/SourceTest.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,88 @@
+/*
+ * 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.sun.hotspot.igv.data;
+
+import java.lang.Integer;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.junit.Assert.*;
+import static org.hamcrest.CoreMatchers.*;
+
+/**
+ *
+ * @author Thomas
+ */
+public class SourceTest {
+
+    public SourceTest() {
+    }
+
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+    }
+
+    @AfterClass
+    public static void tearDownClass() throws Exception {
+    }
+
+    @Before
+    public void setUp() {
+    }
+
+    @After
+    public void tearDown() {
+    }
+
+    /**
+     * Test of getSourceNodes method, of class Source.
+     */
+    @Test
+    public void testBase() {
+        final Source s = new Source();
+
+        final InputNode N1 = new InputNode(1);
+        final InputNode N2 = new InputNode(2);
+
+        s.addSourceNode(N1);
+        assertEquals(s.getSourceNodes(), Arrays.asList(N1));
+        assertEquals(s.getSourceNodesAsSet(), new LinkedHashSet<Integer>(Arrays.asList(1)));
+
+        s.addSourceNode(N2);
+        assertEquals(s.getSourceNodes(), Arrays.asList(N1, N2));
+        assertEquals(s.getSourceNodesAsSet(), new LinkedHashSet<Integer>(Arrays.asList(1, 2)));
+
+        s.addSourceNode(N1);
+        assertEquals(s.getSourceNodes(), Arrays.asList(N1, N2));
+        assertEquals(s.getSourceNodesAsSet(), new LinkedHashSet<Integer>(Arrays.asList(1, 2)));
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/Util.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.sun.hotspot.igv.data;
+
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class Util {
+
+    public static void assertGraphDocumentNotEquals(GraphDocument a, GraphDocument b) {
+        try {
+            assertGraphDocumentEquals(a, b);
+        } catch(AssertionError e) {
+            return;
+        }
+
+        fail("Graphs documents are equal!");
+    }
+
+    public static void assertGraphDocumentEquals(GraphDocument a, GraphDocument b) {
+
+        if (a.getGroups().size() != b.getGroups().size()) {
+            fail();
+        }
+
+        int z = 0;
+        for (Group g : b.getGroups()) {
+
+            Group thisG = a.getGroups().get(z);
+            assertGroupEquals(thisG, g);
+            z++;
+        }
+    }
+
+    public static void assertGroupNotEquals(Group a, Group b) {
+        try {
+            assertGroupEquals(a, b);
+        } catch(AssertionError e) {
+            return;
+        }
+
+        fail("Groups are equal!");
+    }
+
+    public static void assertGroupEquals(Group a, Group b) {
+
+        if (a.getGraphs().size() != b.getGraphs().size()) {
+            fail();
+        }
+
+        int z = 0;
+        for (InputGraph graph : a.getGraphs()) {
+            InputGraph otherGraph = b.getGraphs().get(z);
+            assertGraphEquals(graph, otherGraph);
+            z++;
+        }
+
+        if (a.getMethod() == null || b.getMethod() == null) {
+            if (a.getMethod() != b.getMethod()) {
+                fail();
+            }
+        } else {
+            if (!a.getMethod().equals(b.getMethod())) {
+                fail();
+            }
+        }
+
+        if (a.getAssembly() == null || b.getAssembly() == null) {
+            if (a.getAssembly() != b.getAssembly()) {
+                fail();
+            }
+        } else {
+            if (!a.getAssembly().equals(b.getAssembly())) {
+                fail();
+            }
+        }
+    }
+
+    public static void assertGraphNotEquals(InputGraph a, InputGraph b) {
+        try {
+            assertGraphEquals(a, b);
+        } catch(AssertionError e) {
+            return;
+        }
+
+        fail("Graphs are equal!");
+    }
+
+    public static void assertGraphEquals(InputGraph a, InputGraph b) {
+        
+        if(!a.getNodesAsSet().equals(b.getNodesAsSet())) {
+            fail();
+        }
+        
+        if (!a.getEdges().equals(b.getEdges())) {
+            fail();
+        }
+        
+        if (a.getBlocks().equals(b.getBlocks())) {
+            fail();
+        }
+
+        for (InputNode n : a.getNodes()) {
+            assertEquals(a.getBlock(n), b.getBlock(n));
+        }
+
+        assertEquals(a.getSourceGraphs(), b.getSourceGraphs());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/serialization/ParserTest.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.sun.hotspot.igv.data.serialization;
+
+import com.sun.hotspot.igv.data.GraphDocument;
+import com.sun.hotspot.igv.data.Group;
+import com.sun.hotspot.igv.data.InputBlock;
+import com.sun.hotspot.igv.data.InputEdge;
+import com.sun.hotspot.igv.data.InputGraph;
+import com.sun.hotspot.igv.data.InputMethod;
+import com.sun.hotspot.igv.data.InputNode;
+import com.sun.hotspot.igv.data.Util;
+import java.io.CharArrayWriter;
+import java.io.StringReader;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.openide.xml.XMLUtil;
+import static org.junit.Assert.*;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class ParserTest {
+
+    public ParserTest() {
+    }
+
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+    }
+
+    @AfterClass
+    public static void tearDownClass() throws Exception {
+    }
+
+    @Before
+    public void setUp() {
+    }
+
+    @After
+    public void tearDown() {
+    }
+
+    private void test(GraphDocument document) {
+        final Printer printer = new Printer();
+        final CharArrayWriter writer = new CharArrayWriter();
+        printer.export(writer, document);
+        test(document, writer.toString());
+    }
+
+    private void test(GraphDocument document, String xmlString) {
+        
+        StringReader sr = new StringReader(xmlString);
+        InputSource is = new InputSource(sr);
+
+        try {
+            XMLReader reader = XMLUtil.createXMLReader();
+            Parser parser = new Parser();
+            final GraphDocument parsedDocument = parser.parse(reader, is, null);
+            Util.assertGraphDocumentEquals(document, parsedDocument);
+        } catch (SAXException ex) {
+            fail(ex.toString());
+        }
+    }
+
+    private void testBoth(GraphDocument document, String xmlString) {
+        test(document);
+        test(document, xmlString);
+    }
+
+    /**
+     * Test of graph document serialization
+     */
+    @Test
+    public void testSerialization() {
+        final GraphDocument doc = new GraphDocument();
+
+        test(doc);
+
+        final Group group1 = new Group();
+        doc.addGroup(group1);
+        test(doc);
+
+        final Group group2 = new Group();
+        doc.addGroup(group2);
+        test(doc);
+
+        final InputGraph graph = group1.addGraph("");
+        test(doc);
+
+        graph.addNode(new InputNode(0));
+        test(doc);
+
+        graph.addNode(new InputNode(1));
+        test(doc);
+
+        graph.addNode(new InputNode(2));
+        test(doc);
+
+        graph.addNode(new InputNode(3));
+        test(doc);
+
+        graph.addEdge(new InputEdge((char)0, (char)0, 0, 1));
+        test(doc);
+
+        graph.addEdge(new InputEdge((char)1, (char)1, 0, 1));
+        test(doc);
+
+        graph.addEdge(new InputEdge((char)0, (char)0, 1, 2));
+        test(doc);
+        
+        graph.addEdge(new InputEdge((char)0, (char)0, 2, 3));
+        test(doc);
+
+        group1.setMethod(new InputMethod(group1, "testMethod", "tM", 1));
+        test(doc);
+
+        final InputBlock b1 = graph.addBlock("1");
+        b1.addNode(0);
+        b1.addNode(1);
+
+        final InputBlock b2 = graph.addBlock("2");
+        b2.addNode(2);
+        b2.addNode(3);
+        test(doc);
+
+        final GraphDocument document2 = new GraphDocument();
+        doc.addGraphDocument(document2);
+        test(doc);
+        assertTrue(doc.getGroups().size() == 2);
+
+        final Group group3 = new Group();
+        document2.addGroup(group3);
+        doc.addGraphDocument(document2);
+        assertTrue(doc.getGroups().size() == 3);
+        assertTrue(document2.getGroups().size() == 0);
+
+        doc.clear();
+        test(doc);
+        Util.assertGraphDocumentEquals(doc, new GraphDocument());
+    }
+
+	@Test
+	public void testSimpleExport() {
+		GraphDocument document = new GraphDocument();
+		Group g = new Group();
+		document.addGroup(g);
+        
+		InputGraph graph = g.addGraph("TestGraph");
+		graph.getProperties().setProperty("testName", "testValue");
+
+		InputNode n1 = new InputNode(0);
+		InputNode n2 = new InputNode(1);
+		InputEdge e1 = new InputEdge((char)0, 0, 1);
+		InputEdge e2 = new InputEdge((char)1, 0, 1);
+		graph.addNode(n1);
+		graph.addNode(n2);
+		graph.addEdge(e1);
+		graph.addEdge(e2);
+        
+        test(document);
+	}
+
+	@Test
+	public void testComplexExport() {
+
+		GraphDocument document = new GraphDocument();
+		Group g = new Group();
+		document.addGroup(g);
+
+		InputGraph graph = g.addGraph("TestGraph");
+		graph.getProperties().setProperty("testName", "testValue");
+
+		InputNode n1 = new InputNode(0);
+		InputNode n2 = new InputNode(1);
+		InputEdge e1 = new InputEdge((char)0, 0, 0);
+		InputEdge e2 = new InputEdge((char)1, 1, 1);
+		graph.addNode(n1);
+		graph.addNode(n2);
+		graph.addEdge(e1);
+		graph.addEdge(e2);
+
+		InputGraph graph2 = g.addGraph("TestGraph2");
+		graph2.addNode(n1);
+		InputNode n3 = new InputNode(2);
+		graph2.addNode(n3);
+		InputEdge e3 = new InputEdge((char)0, 0, 2);
+		graph2.addEdge(e3);
+
+        test(document);
+	}
+
+
+    /**
+     * Test of parse method, of class Parser.
+     */
+    @Test
+    public void testParse() {
+        testBoth(new GraphDocument(), "<graphDocument></graphDocument>");
+    }
+
+}
\ No newline at end of file
--- a/src/share/tools/IdealGraphVisualizer/Difference/nbproject/project.xml	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Difference/nbproject/project.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -14,6 +14,14 @@
                         <specification-version>1.0</specification-version>
                     </run-dependency>
                 </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.lookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.6.1</specification-version>
+                    </run-dependency>
+                </dependency>
             </module-dependencies>
             <public-packages>
                 <package>com.sun.hotspot.igv.difference</package>
--- a/src/share/tools/IdealGraphVisualizer/Difference/src/com/sun/hotspot/igv/difference/Difference.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Difference/src/com/sun/hotspot/igv/difference/Difference.java	Wed Jul 27 17:32:44 2011 -0700
@@ -25,15 +25,20 @@
 package com.sun.hotspot.igv.difference;
 
 import com.sun.hotspot.igv.data.Group;
+import com.sun.hotspot.igv.data.InputBlock;
+import com.sun.hotspot.igv.data.InputBlockEdge;
 import com.sun.hotspot.igv.data.InputEdge;
 import com.sun.hotspot.igv.data.InputGraph;
 import com.sun.hotspot.igv.data.InputNode;
+import com.sun.hotspot.igv.data.Pair;
 import com.sun.hotspot.igv.data.Property;
+import com.sun.hotspot.igv.data.services.Scheduler;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
+import org.openide.util.Lookup;
 
 /**
  *
@@ -60,14 +65,14 @@
     }
 
     private static InputGraph createDiffSameGroup(InputGraph a, InputGraph b) {
-        Map<Integer, InputNode> keyMapB = new HashMap<Integer, InputNode>();
+        Map<Integer, InputNode> keyMapB = new HashMap<Integer, InputNode>(b.getNodes().size());
         for (InputNode n : b.getNodes()) {
             Integer key = n.getId();
             assert !keyMapB.containsKey(key);
             keyMapB.put(key, n);
         }
 
-        Set<Pair> pairs = new HashSet<Pair>();
+        Set<NodePair> pairs = new HashSet<NodePair>();
 
         for (InputNode n : a.getNodes()) {
             Integer key = n.getId();
@@ -75,30 +80,80 @@
 
             if (keyMapB.containsKey(key)) {
                 InputNode nB = keyMapB.get(key);
-                pairs.add(new Pair(n, nB));
+                pairs.add(new NodePair(n, nB));
             }
         }
 
         return createDiff(a, b, pairs);
     }
 
-    private static InputGraph createDiff(InputGraph a, InputGraph b, Set<Pair> pairs) {
+    private static void ensureScheduled(InputGraph a) {
+        if (a.getBlocks().isEmpty()) {
+            Scheduler s = Lookup.getDefault().lookup(Scheduler.class);
+            a.clearBlocks();
+            s.schedule(a);
+            a.ensureNodesInBlocks();
+        }
+    }
+
+    private static InputGraph createDiff(InputGraph a, InputGraph b, Set<NodePair> pairs) {
+        ensureScheduled(a);
+        ensureScheduled(b);
+
         Group g = new Group();
         g.setMethod(a.getGroup().getMethod());
         g.setAssembly(a.getGroup().getAssembly());
         g.getProperties().setProperty("name", "Difference");
-        InputGraph graph = new InputGraph(g, null);
-        graph.setName(a.getName() + ", " + b.getName());
-        graph.setIsDifferenceGraph(true);
+        InputGraph graph = g.addGraph(a.getName() + ", " + b.getName(), new Pair<InputGraph, InputGraph>(a, b));
+
+        Map<InputBlock, InputBlock> blocksMap = new HashMap<InputBlock, InputBlock>();
+        for (InputBlock blk : a.getBlocks()) {
+            InputBlock diffblk = graph.addBlock(blk.getName());
+            blocksMap.put(blk, diffblk);
+        }
+        for (InputBlock blk : b.getBlocks()) {
+            InputBlock diffblk = graph.getBlock(blk.getName());
+            if (diffblk == null) {
+                diffblk = graph.addBlock(blk.getName());
+            }
+            blocksMap.put(blk, diffblk);
+        }
+
+        // Difference between block edges
+        Set<Pair<String, String>> aEdges = new HashSet<Pair<String, String>>();
+        for (InputBlockEdge edge : a.getBlockEdges()) {
+            aEdges.add(new Pair<String, String>(edge.getFrom().getName(), edge.getTo().getName()));
+        }
+        for (InputBlockEdge bEdge : b.getBlockEdges()) {
+            InputBlock from = bEdge.getFrom();
+            InputBlock to = bEdge.getTo();
+            Pair<String, String> pair = new Pair<String, String>(from.getName(), to.getName());
+            if (aEdges.contains(pair)) {
+                // same
+                graph.addBlockEdge(blocksMap.get(from), blocksMap.get(to));
+                aEdges.remove(pair);
+            } else {
+                // added
+                InputBlockEdge edge = graph.addBlockEdge(blocksMap.get(from), blocksMap.get(to));
+                edge.setState(InputBlockEdge.State.NEW);
+            }
+        }
+        for (Pair<String, String> deleted : aEdges) {
+            // removed
+            InputBlock from = graph.getBlock(deleted.getLeft());
+            InputBlock to = graph.getBlock(deleted.getRight());
+            InputBlockEdge edge = graph.addBlockEdge(from, to);
+            edge.setState(InputBlockEdge.State.DELETED);
+        }
 
         Set<InputNode> nodesA = new HashSet<InputNode>(a.getNodes());
         Set<InputNode> nodesB = new HashSet<InputNode>(b.getNodes());
 
-        Map<InputNode, InputNode> inputNodeMap = new HashMap<InputNode, InputNode>();
-        for (Pair p : pairs) {
-            InputNode n = p.getN1();
+        Map<InputNode, InputNode> inputNodeMap = new HashMap<InputNode, InputNode>(pairs.size());
+        for (NodePair p : pairs) {
+            InputNode n = p.getLeft();
             assert nodesA.contains(n);
-            InputNode nB = p.getN2();
+            InputNode nB = p.getRight();
             assert nodesB.contains(nB);
 
             nodesA.remove(n);
@@ -107,21 +162,34 @@
             inputNodeMap.put(n, n2);
             inputNodeMap.put(nB, n2);
             graph.addNode(n2);
+            InputBlock block = blocksMap.get(a.getBlock(n));
+            block.addNode(n2.getId());
             markAsChanged(n2, n, nB);
         }
 
         for (InputNode n : nodesA) {
             InputNode n2 = new InputNode(n);
             graph.addNode(n2);
-            markAsNew(n2);
+            InputBlock block = blocksMap.get(a.getBlock(n));
+            block.addNode(n2.getId());
+            markAsDeleted(n2);
             inputNodeMap.put(n, n2);
         }
 
+        int curIndex = 0;
         for (InputNode n : nodesB) {
             InputNode n2 = new InputNode(n);
-            n2.setId(-n2.getId());
+
+            // Find new ID for node of b, does not change the id property
+            while (graph.getNode(curIndex) != null) {
+                curIndex++;
+            }
+
+            n2.setId(curIndex);
             graph.addNode(n2);
-            markAsDeleted(n2);
+            InputBlock block = blocksMap.get(b.getBlock(n));
+            block.addNode(n2.getId());
+            markAsNew(n2);
             inputNodeMap.put(n, n2);
         }
 
@@ -135,11 +203,12 @@
             int to = e.getTo();
             InputNode nodeFrom = inputNodeMap.get(a.getNode(from));
             InputNode nodeTo = inputNodeMap.get(a.getNode(to));
-            char index = e.getToIndex();
+            char fromIndex = e.getFromIndex();
+            char toIndex = e.getToIndex();
 
-            InputEdge newEdge = new InputEdge(index, nodeFrom.getId(), nodeTo.getId());
+            InputEdge newEdge = new InputEdge(fromIndex, toIndex, nodeFrom.getId(), nodeTo.getId());
             if (!newEdges.contains(newEdge)) {
-                markAsNew(newEdge);
+                markAsDeleted(newEdge);
                 newEdges.add(newEdge);
                 graph.addEdge(newEdge);
             }
@@ -150,11 +219,12 @@
             int to = e.getTo();
             InputNode nodeFrom = inputNodeMap.get(b.getNode(from));
             InputNode nodeTo = inputNodeMap.get(b.getNode(to));
-            char index = e.getToIndex();
+            char fromIndex = e.getFromIndex();
+            char toIndex = e.getToIndex();
 
-            InputEdge newEdge = new InputEdge(index, nodeFrom.getId(), nodeTo.getId());
+            InputEdge newEdge = new InputEdge(fromIndex, toIndex, nodeFrom.getId(), nodeTo.getId());
             if (!newEdges.contains(newEdge)) {
-                markAsDeleted(newEdge);
+                markAsNew(newEdge);
                 newEdges.add(newEdge);
                 graph.addEdge(newEdge);
             } else {
@@ -166,24 +236,20 @@
             }
         }
 
-        g.addGraph(graph);
         return graph;
     }
 
-    private static class Pair {
+    private static class NodePair extends Pair<InputNode, InputNode> {
+
 
-        private InputNode n1;
-        private InputNode n2;
-
-        public Pair(InputNode n1, InputNode n2) {
-            this.n1 = n1;
-            this.n2 = n2;
+        public NodePair(InputNode n1, InputNode n2) {
+            super(n1, n2);
         }
 
         public double getValue() {
 
             double result = 0.0;
-            for (Property p : n1.getProperties()) {
+            for (Property p : getLeft().getProperties()) {
                 double faktor = 1.0;
                 for (String forbidden : IGNORE_PROPERTIES) {
                     if (p.getName().equals(forbidden)) {
@@ -191,7 +257,7 @@
                         break;
                     }
                 }
-                String p2 = n2.getProperties().get(p.getName());
+                String p2 = getRight().getProperties().get(p.getName());
                 result += evaluate(p.getValue(), p2) * faktor;
             }
 
@@ -208,21 +274,13 @@
                 return (double) (Math.abs(p.length() - p2.length())) / p.length() + 0.5;
             }
         }
-
-        public InputNode getN1() {
-            return n1;
-        }
-
-        public InputNode getN2() {
-            return n2;
-        }
     }
 
     private static InputGraph createDiff(InputGraph a, InputGraph b) {
 
         Set<InputNode> matched = new HashSet<InputNode>();
 
-        Set<Pair> pairs = new HashSet<Pair>();
+        Set<NodePair> pairs = new HashSet<NodePair>();
         for (InputNode n : a.getNodes()) {
             String s = n.getProperties().get(MAIN_PROPERTY);
             if (s == null) {
@@ -235,18 +293,18 @@
                 }
 
                 if (s.equals(s2)) {
-                    Pair p = new Pair(n, n2);
+                    NodePair p = new NodePair(n, n2);
                     pairs.add(p);
                 }
             }
         }
 
-        Set<Pair> selectedPairs = new HashSet<Pair>();
+        Set<NodePair> selectedPairs = new HashSet<NodePair>();
         while (pairs.size() > 0) {
 
             double min = Double.MAX_VALUE;
-            Pair minPair = null;
-            for (Pair p : pairs) {
+            NodePair minPair = null;
+            for (NodePair p : pairs) {
                 double cur = p.getValue();
                 if (cur < min) {
                     minPair = p;
@@ -259,9 +317,9 @@
             } else {
                 selectedPairs.add(minPair);
 
-                Set<Pair> toRemove = new HashSet<Pair>();
-                for (Pair p : pairs) {
-                    if (p.getN1() == minPair.getN1() || p.getN2() == minPair.getN2()) {
+                Set<NodePair> toRemove = new HashSet<NodePair>();
+                for (NodePair p : pairs) {
+                    if (p.getLeft() == minPair.getLeft() || p.getRight() == minPair.getRight()) {
                         toRemove.add(p);
                     }
                 }
--- a/src/share/tools/IdealGraphVisualizer/Filter/nbproject/project.xml	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Filter/nbproject/project.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -28,7 +28,15 @@
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>1</release-version>
-                        <specification-version>1.4.1</specification-version>
+                        <specification-version>1.16.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.awt</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.30.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -36,7 +44,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.5.1</specification-version>
+                        <specification-version>7.18.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -44,7 +52,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.3</specification-version>
+                        <specification-version>7.46.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -52,7 +60,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.2.0.1</specification-version>
+                        <specification-version>7.20.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -60,7 +68,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.9.0.1</specification-version>
+                        <specification-version>8.14.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.lookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.6.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -68,7 +84,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.16</specification-version>
+                        <specification-version>6.39.1</specification-version>
                     </run-dependency>
                 </dependency>
             </module-dependencies>
--- a/src/share/tools/IdealGraphVisualizer/Filter/src/META-INF/services/com.sun.hotspot.igv.filter.ScriptEngineAbstraction	Tue Jun 28 10:57:38 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-com.sun.hotspot.igv.filter.JavaSE6ScriptEngine
\ No newline at end of file
--- a/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/CombineFilter.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/CombineFilter.java	Wed Jul 27 17:32:44 2011 -0700
@@ -77,7 +77,7 @@
                         }
 
                         assert slot != null;
-                        slot.setName(f.getProperties().get("dump_spec"));
+                        slot.setText(f.getProperties().get("dump_spec"));
                         if (f.getProperties().get("short_name") != null) {
                             slot.setShortName(f.getProperties().get("short_name"));
                         } else {
@@ -122,7 +122,7 @@
                                     pos = Integer.parseInt(succ.getProperties().get("con"));
                                 }
                                 OutputSlot slot = f.createOutputSlot(pos);
-                                slot.setName(succ.getProperties().get("dump_spec"));
+                                slot.setText(succ.getProperties().get("dump_spec"));
                                 if (succ.getProperties().get("short_name") != null) {
                                     slot.setShortName(succ.getProperties().get("short_name"));
                                 } else {
--- a/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/CustomFilter.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/CustomFilter.java	Wed Jul 27 17:32:44 2011 -0700
@@ -38,6 +38,7 @@
 import org.openide.filesystems.Repository;
 import org.openide.filesystems.FileSystem;
 import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
 import org.openide.util.Exceptions;
 import org.openide.util.Lookup;
 
@@ -89,7 +90,9 @@
     public boolean openInEditor() {
         EditFilterDialog dialog = new EditFilterDialog(CustomFilter.this);
         dialog.setVisible(true);
-        return dialog.wasAccepted();
+        boolean result = dialog.wasAccepted();
+        this.getChangedEvent().fire();
+        return result;
     }
 
     @Override
@@ -100,18 +103,12 @@
     public static ScriptEngineAbstraction getEngine() {
         if (engine == null) {
 
+            Collection<? extends ScriptEngineAbstraction> list = Lookup.getDefault().lookupAll(ScriptEngineAbstraction.class);
             ScriptEngineAbstraction chosen = null;
-            try {
-                Collection<? extends ScriptEngineAbstraction> list = Lookup.getDefault().lookupAll(ScriptEngineAbstraction.class);
-                for (ScriptEngineAbstraction s : list) {
-                    if (s.initialize(getJsHelperText())) {
-                        if (chosen == null || !(chosen instanceof JavaSE6ScriptEngine)) {
-                            chosen = s;
-                        }
-                    }
+            for (ScriptEngineAbstraction s : list) {
+                if (s.initialize(getJsHelperText())) {
+                    chosen = s;
                 }
-            } catch (NoClassDefFoundError ncdfe) {
-                Logger.getLogger("global").log(Level.SEVERE, null, ncdfe);
             }
 
             if (chosen == null) {
@@ -130,8 +127,7 @@
         InputStream is = null;
         StringBuilder sb = new StringBuilder("importPackage(Packages.com.sun.hotspot.igv.filter);importPackage(Packages.com.sun.hotspot.igv.graph);importPackage(Packages.com.sun.hotspot.igv.data);importPackage(Packages.com.sun.hotspot.igv.util);importPackage(java.awt);");
         try {
-            FileSystem fs = Repository.getDefault().getDefaultFileSystem();
-            FileObject fo = fs.getRoot().getFileObject(JAVASCRIPT_HELPER_ID);
+            FileObject fo = FileUtil.getConfigRoot().getFileObject(JAVASCRIPT_HELPER_ID);
             is = fo.getInputStream();
             BufferedReader r = new BufferedReader(new InputStreamReader(is));
             String s;
--- a/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/EditFilterDialog.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/EditFilterDialog.java	Wed Jul 27 17:32:44 2011 -0700
@@ -137,17 +137,17 @@
     }// </editor-fold>//GEN-END:initComponents
 
 private void okButtonClicked(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonClicked
-        this.customFilter.setName(this.nameTextField.getText());
-        this.customFilter.setCode(this.sourceTextArea.getText());
-        accepted = true;
-        setVisible(false);
+	this.customFilter.setName(this.nameTextField.getText());
+	this.customFilter.setCode(this.sourceTextArea.getText());
+	accepted = true;
+	setVisible(false);
 }//GEN-LAST:event_okButtonClicked
 
 private void cancelButtonClicked(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonClicked
-        setVisible(false);
+	setVisible(false);
 }//GEN-LAST:event_cancelButtonClicked
-
-
+	
+	
     // Variables declaration - do not modify//GEN-BEGIN:variables
     private javax.swing.JButton cancelButton;
     private javax.swing.JScrollPane jScrollPane1;
@@ -157,5 +157,5 @@
     private javax.swing.JLabel sourceLabel;
     private javax.swing.JTextArea sourceTextArea;
     // End of variables declaration//GEN-END:variables
-
+	
 }
--- a/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/FilterChain.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/FilterChain.java	Wed Jul 27 17:32:44 2011 -0700
@@ -26,6 +26,7 @@
 import com.sun.hotspot.igv.graph.Diagram;
 import com.sun.hotspot.igv.data.ChangedEvent;
 import com.sun.hotspot.igv.data.ChangedEventProvider;
+import com.sun.hotspot.igv.data.ChangedListener;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -38,18 +39,21 @@
 
     private List<Filter> filters;
     private transient ChangedEvent<FilterChain> changedEvent;
-    private boolean fireEvents;
+    
+    private ChangedListener<Filter> changedListener = new ChangedListener<Filter>() {
+        public void changed(Filter source) {
+            changedEvent.fire();
+        }
+    };
 
     public FilterChain() {
         filters = new ArrayList<Filter>();
         changedEvent = new ChangedEvent<FilterChain>(this);
-        this.fireEvents = true;
     }
 
     public FilterChain(FilterChain f) {
         this.filters = new ArrayList<Filter>(f.filters);
         changedEvent = new ChangedEvent<FilterChain>(this);
-        this.fireEvents = true;
     }
 
     public ChangedEvent<FilterChain> getChangedEvent() {
@@ -84,29 +88,12 @@
         }
     }
 
-    public void beginAtomic() {
-        this.fireEvents = false;
-    }
-
-    public void endAtomic() {
-        this.fireEvents = true;
-        changedEvent.fire();
-    }
 
     public void addFilter(Filter filter) {
         assert filter != null;
         filters.add(filter);
-        if (fireEvents) {
-            changedEvent.fire();
-        }
-    }
-
-    public void addFilterSameSequence(Filter filter) {
-        assert filter != null;
-        filters.add(filter);
-        if (fireEvents) {
-            changedEvent.fire();
-        }
+        filter.getChangedEvent().addListener(changedListener);
+        changedEvent.fire();
     }
 
     public boolean containsFilter(Filter filter) {
@@ -116,9 +103,8 @@
     public void removeFilter(Filter filter) {
         assert filters.contains(filter);
         filters.remove(filter);
-        if (fireEvents) {
-            changedEvent.fire();
-        }
+        filter.getChangedEvent().removeListener(changedListener);
+        changedEvent.fire();
     }
 
     public void moveFilterUp(Filter filter) {
@@ -128,9 +114,7 @@
             filters.remove(index);
             filters.add(index - 1, filter);
         }
-        if (fireEvents) {
-            changedEvent.fire();
-        }
+        changedEvent.fire();
     }
 
     public void moveFilterDown(Filter filter) {
@@ -140,16 +124,10 @@
             filters.remove(index);
             filters.add(index + 1, filter);
         }
-        if (fireEvents) {
-            changedEvent.fire();
-        }
+        changedEvent.fire();
     }
 
     public List<Filter> getFilters() {
         return Collections.unmodifiableList(filters);
     }
-
-    public void clear() {
-        filters.clear();
-    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/GradientColorFilter.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,163 @@
+/*
+ * 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.sun.hotspot.igv.filter;
+
+import com.sun.hotspot.igv.graph.Diagram;
+import com.sun.hotspot.igv.graph.Figure;
+import java.awt.Color;
+import java.awt.LinearGradientPaint;
+import java.awt.PaintContext;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.geom.AffineTransform;
+import java.awt.image.Raster;
+import java.util.List;
+
+/**
+ * Filter that colors nodes using a customizable color gradient, based on how
+ * a numeric property is located in a specified interval.
+ * 
+ * @author Peter Hofer
+ */
+public class GradientColorFilter extends AbstractFilter {
+
+    public static final String LINEAR = "LINEAR";
+    public static final String LOGARITHMIC = "LOGARITHMIC";
+
+    private String propertyName = "probability";
+    private float minValue = 0;
+    private float maxValue = 500;
+    private float[] fractions = {0, 0.5f, 1};
+    private Color[] colors = {Color.BLUE, Color.YELLOW, Color.RED};
+    private int shadeCount = 8;
+    private String mode = LINEAR;
+
+    public String getName() {
+        return "Gradient Color Filter";
+    }
+
+    public void apply(Diagram d) {
+        boolean logarithmic = mode.equalsIgnoreCase(LOGARITHMIC);
+        if (!logarithmic && !mode.equalsIgnoreCase(LINEAR)) {
+            throw new RuntimeException("Unknown mode: " + mode);
+        }
+
+        Rectangle bounds = new Rectangle(shadeCount, 1);
+        LinearGradientPaint lgp = new LinearGradientPaint(bounds.x, bounds.y, bounds.width, bounds.y, fractions, colors);
+        PaintContext context = lgp.createContext(null, bounds, bounds.getBounds2D(), AffineTransform.getTranslateInstance(0, 0), new RenderingHints(null));
+        Raster raster = context.getRaster(bounds.x, bounds.y, bounds.width, bounds.height);
+        int[] rgb = raster.getPixels(bounds.x, bounds.y, bounds.width, bounds.height, (int[]) null);
+        Color[] shades = new Color[rgb.length / 3];
+        for (int i = 0; i < shades.length; ++i) {
+            shades[i] = new Color(rgb[i * 3], rgb[i * 3 + 1], rgb[i * 3 + 2]);
+        }
+
+        List<Figure> figures = d.getFigures();
+        for (Figure f : figures) {
+            String property = f.getProperties().get(propertyName);
+            if (property != null) {
+                try {
+                    float value = Float.parseFloat(property);
+
+                    Color nodeColor;
+                    if (value <= minValue) {
+                        nodeColor = colors[0];
+                    } else if (value >= maxValue) {
+                        nodeColor = colors[colors.length - 1];
+                    } else {
+                        double normalized = value - minValue;
+                        double interval = maxValue - minValue;
+                        int index;
+                        // Use Math.ceil() to make values above zero distinguishable from zero
+                        if (logarithmic) {
+                            index = (int) Math.ceil(shades.length * Math.log(1 + normalized) / Math.log(1 + interval));
+                        } else {
+                            index = (int) Math.ceil(shades.length * normalized / interval);
+                        }
+                        nodeColor = shades[index];
+                    }
+                    f.setColor(nodeColor);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    public String getPropertyName() {
+        return propertyName;
+    }
+
+    public void setPropertyName(String propertyName) {
+        this.propertyName = propertyName;
+    }
+
+    public float getMinValue() {
+        return minValue;
+    }
+
+    public void setMinValue(float minValue) {
+        this.minValue = minValue;
+    }
+
+    public float getMaxValue() {
+        return maxValue;
+    }
+
+    public void setMaxValue(float maxValue) {
+        this.maxValue = maxValue;
+    }
+
+    public float[] getFractions() {
+        return fractions;
+    }
+
+    public void setFractions(float[] fractions) {
+        this.fractions = fractions;
+    }
+
+    public Color[] getColors() {
+        return colors;
+    }
+
+    public void setColors(Color[] colors) {
+        this.colors = colors;
+    }
+
+    public int getShadeCount() {
+        return shadeCount;
+    }
+
+    public void setShadeCount(int shadeCount) {
+        this.shadeCount = shadeCount;
+    }
+
+    public String getMode() {
+        return mode;
+    }
+
+    public void setMode(String mode) {
+        this.mode = mode;
+    }
+}
--- a/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/JavaSE6ScriptEngine.java	Tue Jun 28 10:57:38 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.sun.hotspot.igv.filter;
-
-import com.sun.hotspot.igv.graph.Diagram;
-import javax.script.Bindings;
-import javax.script.ScriptContext;
-import javax.script.ScriptEngine;
-import javax.script.ScriptEngineManager;
-import javax.script.ScriptException;
-import org.openide.util.Exceptions;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public class JavaSE6ScriptEngine implements ScriptEngineAbstraction {
-
-    private ScriptEngine engine;
-    private Bindings bindings;
-
-    public boolean initialize(String jsHelperText) {
-        try {
-            ScriptEngineManager sem = new ScriptEngineManager();
-            ScriptEngine e = sem.getEngineByName("ECMAScript");
-            engine = e;
-            e.eval(jsHelperText);
-            Bindings b = e.getContext().getBindings(ScriptContext.ENGINE_SCOPE);
-            b.put("IO", System.out);
-            bindings = b;
-            return true;
-        } catch (Exception e) {
-            return false;
-        }
-    }
-
-    public void execute(Diagram d, String code) {
-        try {
-            Bindings b = bindings;
-            b.put("graph", d);
-            engine.eval(code, b);
-        } catch (ScriptException ex) {
-            Exceptions.printStackTrace(ex);
-        }
-    }
-}
--- a/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/RemoveFilter.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/RemoveFilter.java	Wed Jul 27 17:32:44 2011 -0700
@@ -25,9 +25,7 @@
 
 import com.sun.hotspot.igv.graph.Diagram;
 import com.sun.hotspot.igv.graph.Figure;
-import com.sun.hotspot.igv.graph.InputSlot;
 import com.sun.hotspot.igv.graph.Selector;
-import com.sun.hotspot.igv.data.Properties;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
@@ -52,48 +50,26 @@
     }
 
     public void apply(Diagram diagram) {
-
         for (RemoveRule r : rules) {
+            List<Figure> selected = r.getSelector().selected(diagram);
+            Set<Figure> toRemove = new HashSet<Figure>(selected);
 
-            List<Figure> list = r.getSelector().selected(diagram);
-            Set<Figure> figuresToRemove = new HashSet<Figure>();
-
-            List<Figure> protectedFigures = null;
-            if (r.getRemoveAllWithoutPredecessor()) {
-                protectedFigures = diagram.getRootFigures();
+            if (r.getRemoveOrphans()) {
+                boolean changed;
+                do {
+                    changed = false;
+                    for (Figure f : diagram.getFigures()) {
+                        if (!toRemove.contains(f)) {
+                            if (toRemove.containsAll(f.getPredecessors()) && toRemove.containsAll(f.getSuccessors())) {
+                                toRemove.add(f);
+                                changed = true;
+                            }
+                        }
+                    }
+                } while (changed);
             }
 
-            for (Figure f : list) {
-                if (r.getRemoveOnlyInputs()) {
-                    List<InputSlot> inputSlots = new ArrayList<InputSlot>();
-                    for (InputSlot is : f.getInputSlots()) {
-                        inputSlots.add(is);
-                    }
-                    for (InputSlot is : inputSlots) {
-                        f.removeSlot(is);
-                    }
-
-                    f.createInputSlot();
-                } else {
-                    figuresToRemove.add(f);
-                }
-            }
-
-            if (r.getRemoveAllWithoutPredecessor()) {
-                boolean progress = true;
-                while (progress) {
-                    List<Figure> rootFigures = diagram.getRootFigures();
-                    progress = false;
-                    for (Figure f : rootFigures) {
-                        if (!protectedFigures.contains(f)) {
-                            figuresToRemove.add(f);
-                            progress = true;
-                        }
-                    }
-                }
-            }
-
-            diagram.removeAllFigures(figuresToRemove);
+            diagram.removeAllFigures(toRemove);
         }
     }
 
@@ -104,29 +80,23 @@
     public static class RemoveRule {
 
         private Selector selector;
-        private boolean removeAllWithoutPredecessor;
-        private boolean removeOnlyInputs;
+        private boolean removeOrphans;
 
-        public RemoveRule(Selector selector, boolean b) {
-            this(selector, b, false);
+        public RemoveRule(Selector selector) {
+            this(selector, false);
         }
 
-        public RemoveRule(Selector selector, boolean removeAllWithoutPredecessor, boolean removeOnlyInputs) {
+        public RemoveRule(Selector selector, boolean removeOrphans) {
             this.selector = selector;
-            this.removeOnlyInputs = removeOnlyInputs;
-            this.removeAllWithoutPredecessor = removeAllWithoutPredecessor;
+            this.removeOrphans = removeOrphans;
         }
 
         public Selector getSelector() {
             return selector;
         }
 
-        public boolean getRemoveOnlyInputs() {
-            return removeOnlyInputs;
-        }
-
-        public boolean getRemoveAllWithoutPredecessor() {
-            return removeAllWithoutPredecessor;
+        public boolean getRemoveOrphans() {
+            return removeOrphans;
         }
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/RemoveInputsFilter.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/RemoveInputsFilter.java	Wed Jul 27 17:32:44 2011 -0700
@@ -73,7 +73,7 @@
                         }
                         is.removeAllConnections();
                         is.setShortName("X");
-                        is.setName(sb.toString());
+                        is.setText(sb.toString());
                         last.add(is);
                     } else {
                         last.clear();
@@ -91,10 +91,10 @@
                         if (i != 0) {
                             sb.append("<BR>");
                         }
-                        sb.append(is2.getName());
+                        sb.append(is2.getText());
                     }
 
-                    first.setName(sb.toString());
+                    first.setText(sb.toString());
 
                     for (int i = 1; i < last.size(); i++) {
                         f.removeSlot(last.get(i));
--- a/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/RemoveSelfLoopsFilter.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/RemoveSelfLoopsFilter.java	Wed Jul 27 17:32:44 2011 -0700
@@ -72,7 +72,7 @@
                     }
 
                     c.getInputSlot().setShortName("O");
-                    c.getInputSlot().setName("Self Loop");
+                    c.getInputSlot().setText("Self Loop");
                 }
             }
         }
--- a/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/SplitFilter.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/SplitFilter.java	Wed Jul 27 17:32:44 2011 -0700
@@ -39,25 +39,50 @@
 
     private String name;
     private Selector selector;
+    private String propertyName;
 
-    public SplitFilter(String name, Selector selector) {
+    public SplitFilter(String name, Selector selector, String propertyName) {
         this.name = name;
         this.selector = selector;
+        this.propertyName = propertyName;
     }
 
     public String getName() {
         return name;
     }
-
+    
     public void apply(Diagram d) {
         List<Figure> list = selector.selected(d);
 
         for (Figure f : list) {
+            
+            for (InputSlot is : f.getInputSlots()) {
+                for (Connection c : is.getConnections()) {
+                    OutputSlot os = c.getOutputSlot();
+                    if (f.getSource().getSourceNodes().size() > 0) {
+                        os.getSource().addSourceNodes(f.getSource());
+                        os.setAssociatedNode(f.getSource().getSourceNodes().get(0));
+                        os.setColor(f.getColor());
+                    }
+
+
+                    String s = Figure.resolveString(propertyName, f.getProperties());
+                    if (s != null) {
+                        os.setShortName(s);
+                    }
+
+                }
+            }
             for (OutputSlot os : f.getOutputSlots()) {
                 for (Connection c : os.getConnections()) {
                     InputSlot is = c.getInputSlot();
-                    is.setName(f.getProperties().get("dump_spec"));
-                    String s = f.getProperties().get("short_name");
+                    if (f.getSource().getSourceNodes().size() > 0) {
+                        is.getSource().addSourceNodes(f.getSource());
+                        is.setAssociatedNode(f.getSource().getSourceNodes().get(0));
+                        is.setColor(f.getColor());
+                    }
+
+                    String s = Figure.resolveString(propertyName, f.getProperties());
                     if (s != null) {
                         is.setShortName(s);
                     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/UnconnectedSlotFilter.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,78 @@
+/*
+ * 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.sun.hotspot.igv.filter;
+
+import com.sun.hotspot.igv.graph.Diagram;
+import com.sun.hotspot.igv.graph.Figure;
+import com.sun.hotspot.igv.graph.InputSlot;
+import com.sun.hotspot.igv.graph.OutputSlot;
+import com.sun.hotspot.igv.graph.Slot;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Filter that hides slots with no connections.
+ */
+public class UnconnectedSlotFilter extends AbstractFilter {
+
+    private final boolean removeInputs;
+    private final boolean removeOutputs;
+
+    public UnconnectedSlotFilter(boolean inputs, boolean outputs) {
+        this.removeInputs = inputs;
+        this.removeOutputs = outputs;
+    }
+
+    public String getName() {
+        return "Unconnected Slot Filter";
+    }
+
+    public void apply(Diagram d) {
+        if (!removeInputs && !removeOutputs) {
+            return;
+        }
+
+        List<Figure> figures = d.getFigures();
+        for (Figure f : figures) {
+            List<Slot> remove = new ArrayList<Slot>();
+            if (removeInputs) {
+                for (InputSlot is : f.getInputSlots()) {
+                    if (is.getConnections().isEmpty()) {
+                        remove.add(is);
+                    }
+                }
+            }
+            if (removeOutputs) {
+                for (OutputSlot os : f.getOutputSlots()) {
+                    if (os.getConnections().isEmpty()) {
+                        remove.add(os);
+                    }
+                }
+            }
+            for (Slot s : remove) {
+                f.removeSlot(s);
+            }
+        }
+    }
+}
--- a/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/helper.js	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/helper.js	Wed Jul 27 17:32:44 2011 -0700
@@ -21,26 +21,35 @@
  * questions.
  *
  */
-
+ 
  /**
  *
  * @author Thomas Wuerthinger
  */
-
+ 
 function colorize(property, regexp, color) {
     var f = new ColorFilter("");
     f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp)), color));
-    f.apply(graph);
+    f.apply(graph); 
 }
 
 function remove(property, regexp) {
     var f = new RemoveFilter("");
-    f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp)), false, false));
+    f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp))));
     f.apply(graph);
 }
 
-function split(property, regexp) {
-    var f = new SplitFilter("", new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp)));
+function removeIncludingOrphans(property, regexp) {
+    var f = new RemoveFilter("");
+    f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp)), true));
+    f.apply(graph);
+}
+
+function split(property, regexp, propertyName) {
+    if (propertyName == undefined) {
+        propertyName = graph.getNodeText();
+    }
+    var f = new SplitFilter("", new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp)), propertyName);
     f.apply(graph);
 }
 
@@ -56,6 +65,40 @@
     f.apply(graph);
 }
 
+function removeUnconnectedSlots(inputs, outputs) {
+    var f = new UnconnectedSlotFilter(inputs, outputs);
+    f.apply(graph);
+}
+
+function colorizeGradient(property, min, max) {
+    var f = new GradientColorFilter();
+    f.setPropertyName(property);
+    f.setMinValue(min);
+    f.setMaxValue(max);
+    f.apply(graph);
+}
+
+function colorizeGradientWithMode(property, min, max, mode) {
+    var f = new GradientColorFilter();
+    f.setPropertyName(property);
+    f.setMinValue(min);
+    f.setMaxValue(max);
+    f.setMode(mode);
+    f.apply(graph);
+}
+
+function colorizeGradientCustom(property, min, max, mode, colors, fractions, nshades) {
+    var f = new GradientColorFilter();
+    f.setPropertyName(property);
+    f.setMinValue(min);
+    f.setMaxValue(max);
+    f.setMode(mode);
+    f.setColors(colors);
+    f.setFractions(fractions);
+    f.setShadeCount(nshades);
+    f.apply(graph);
+}
+
 var black = Color.black;
 var blue = Color.blue;
 var cyan = Color.cyan;
@@ -68,4 +111,4 @@
 var pink = Color.pink
 var red = Color.red;
 var yellow = Color.yellow;
-var white = Color.white;
+var white = Color.white;
\ No newline at end of file
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/nbproject/build-impl.xml	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/nbproject/build-impl.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -4,6 +4,13 @@
 ***         EDIT ../build.xml INSTEAD         ***
 -->
 <project name="com.sun.hotspot.igv.filterwindow-impl" basedir="..">
+    <fail message="Please build using Ant 1.7.1 or higher.">
+        <condition>
+            <not>
+                <antversion atleast="1.7.1"/>
+            </not>
+        </condition>
+    </fail>
     <property file="nbproject/private/suite-private.properties"/>
     <property file="nbproject/suite.properties"/>
     <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
@@ -16,13 +23,21 @@
             <property name="@{name}" value="${@{value}}"/>
         </sequential>
     </macrodef>
+    <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="property"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{property}" value="@{value}"/>
+        </sequential>
+    </macrodef>
     <property file="${user.properties.file}"/>
     <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
-    <nbmproject2:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
-    <fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'">
+    <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
         <condition>
             <not>
-                <available file="${harness.dir}" type="dir"/>
+                <contains string="${cluster.path.evaluated}" substring="platform"/>
             </not>
         </condition>
     </fail>
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/nbproject/genfiles.properties	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/nbproject/genfiles.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -1,8 +1,5 @@
-build.xml.data.CRC32=401b2654
-build.xml.script.CRC32=9c158403
-build.xml.stylesheet.CRC32=79c3b980
 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
 # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
-nbproject/build-impl.xml.data.CRC32=401b2654
-nbproject/build-impl.xml.script.CRC32=19fb08e0
-nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
+nbproject/build-impl.xml.data.CRC32=09ba2a87
+nbproject/build-impl.xml.script.CRC32=e4293f0e
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.45.1
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/nbproject/project.xml	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/nbproject/project.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -43,7 +43,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.6.1.1</specification-version>
+                        <specification-version>6.21.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -51,7 +51,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.5.1</specification-version>
+                        <specification-version>7.18.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -59,7 +59,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.12.1</specification-version>
+                        <specification-version>6.34.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -67,7 +67,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.3.1</specification-version>
+                        <specification-version>7.46.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -75,7 +75,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.7.1</specification-version>
+                        <specification-version>7.20.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -83,7 +83,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.2.1.1</specification-version>
+                        <specification-version>7.20.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -91,7 +91,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.10.1.1</specification-version>
+                        <specification-version>8.14.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.lookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.6.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -99,7 +107,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.18.1</specification-version>
+                        <specification-version>6.39.1</specification-version>
                     </run-dependency>
                 </dependency>
             </module-dependencies>
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/Bundle.properties	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/Bundle.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -1,3 +1,3 @@
 OpenIDE-Module-Name=FilterWindow
-CTL_FilterTopComponent=Filter Window
-HINT_FilterTopComponent=This is a Filter window
+CTL_FilterTopComponent=Filters
+HINT_FilterTopComponent=Allows to choose active filters and modify them.
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckNodeListModel.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckNodeListModel.java	Wed Jul 27 17:32:44 2011 -0700
@@ -24,7 +24,7 @@
 package com.sun.hotspot.igv.filterwindow;
 
 import org.openide.explorer.view.NodeListModel;
-import org.openide.nodes.Node;
+import org.openide.explorer.view.Visualizer;
 
 /**
  *
@@ -32,15 +32,11 @@
  */
 public class CheckNodeListModel extends NodeListModel {
 
-    private Node rootNode;
-
-    @Override
-    public void setNode(Node rootNode) {
-        this.rootNode = rootNode;
-        super.setNode(rootNode);
-    }
-
     public CheckNode getCheckNodeAt(int index) {
-        return (CheckNode) rootNode.getChildren().getNodes()[index];
+        Object item = getElementAt(index);
+        if (item != null) {
+            return (CheckNode) Visualizer.findNode(item);
+        }
+        return null;
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterTopComponent.form	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterTopComponent.form	Wed Jul 27 17:32:44 2011 -0700
@@ -3,6 +3,7 @@
 <Form version="1.2" maxVersion="1.2" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
   <AuxValues>
     <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
     <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
     <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
     <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="2"/>
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterTopComponent.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterTopComponent.java	Wed Jul 27 17:32:44 2011 -0700
@@ -82,9 +82,10 @@
 import org.openide.filesystems.Repository;
 import org.openide.filesystems.FileSystem;
 import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
 
 /**
- *
+ * 
  * @author Thomas Wuerthinger
  */
 public final class FilterTopComponent extends TopComponent implements LookupListener, ExplorerManager.Provider {
@@ -139,7 +140,7 @@
 
         if (s != customFilterSetting) {
             FilterChain chain = getFilterChain();
-            chain.beginAtomic();
+            chain.getChangedEvent().beginAtomic();
             List<Filter> toRemove = new ArrayList<Filter>();
             for (Filter f : chain.getFilters()) {
                 if (!s.containsFilter(f)) {
@@ -156,7 +157,7 @@
                 }
             }
 
-            chain.endAtomic();
+            chain.getChangedEvent().endAtomic();
             filterSettingsChangedEvent.fire();
         } else {
             this.updateComboBoxSelection();
@@ -267,22 +268,18 @@
         }
     }
 
-    private class FilterChildren extends Children.Keys implements ChangedListener<CheckNode> {
+    private class FilterChildren extends Children.Keys<Filter> implements ChangedListener<CheckNode> {
+
+        private HashMap<Filter, Node> nodeHash = new HashMap<Filter, Node>();
 
-        //private Node[] oldSelection;
-        //private ArrayList<Node> newSelection;
-        private HashMap<Object, Node> nodeHash = new HashMap<Object, Node>();
-
-        protected Node[] createNodes(Object object) {
-            if (nodeHash.containsKey(object)) {
-                return new Node[]{nodeHash.get(object)};
+        protected Node[] createNodes(Filter filter) {
+            if (nodeHash.containsKey(filter)) {
+                return new Node[]{nodeHash.get(filter)};
             }
 
-            assert object instanceof Filter;
-            Filter filter = (Filter) object;
-            com.sun.hotspot.igv.filterwindow.FilterNode node = new com.sun.hotspot.igv.filterwindow.FilterNode(filter);
+            FilterNode node = new FilterNode(filter);
             node.getSelectionChangedEvent().addListener(this);
-            nodeHash.put(object, node);
+            nodeHash.put(filter, node);
             return new Node[]{node};
         }
 
@@ -297,6 +294,7 @@
             setBefore(false);
         }
 
+        @Override
         protected void addNotify() {
             setKeys(sequence.getFilters());
             updateSelection();
@@ -322,12 +320,7 @@
     }
 
     public FilterChain getFilterChain() {
-        return filterChain;/*
-    EditorTopComponent tc = EditorTopComponent.getActive();
-    if (tc == null) {
-    return filterChain;
-    }
-    return tc.getFilterChain();*/
+        return filterChain;
     }
 
     private FilterTopComponent() {
@@ -427,9 +420,7 @@
     }
 
     public void initFilters() {
-
-        FileSystem fs = Repository.getDefault().getDefaultFileSystem();
-        FileObject folder = fs.getRoot().getFileObject(FOLDER_ID);
+        FileObject folder = FileUtil.getConfigRoot().getFileObject(FOLDER_ID);
         FileObject[] children = folder.getChildren();
 
         List<CustomFilter> customFilters = new ArrayList<CustomFilter>();
@@ -447,13 +438,12 @@
                 is = fo.getInputStream();
                 BufferedReader r = new BufferedReader(new InputStreamReader(is));
                 String s;
-                StringBuffer sb = new StringBuffer();
+                StringBuilder sb = new StringBuilder();
                 while ((s = r.readLine()) != null) {
                     sb.append(s);
                     sb.append("\n");
                 }
                 code = sb.toString();
-
             } catch (FileNotFoundException ex) {
                 Exceptions.printStackTrace(ex);
             } catch (IOException ex) {
@@ -566,7 +556,6 @@
         return PREFERRED_ID;
     }
 
-    @Override
     public ExplorerManager getExplorerManager() {
         return manager;
     }
@@ -586,11 +575,6 @@
 
     public void resultChanged(LookupEvent lookupEvent) {
         setChain(Utilities.actionsGlobalContext().lookup(FilterChain.class));
-    /*
-    EditorTopComponent tc = EditorTopComponent.getActive();
-    if (tc != null) {
-    setChain(tc.getFilterChain());
-    }*/
     }
 
     public void setChain(FilterChain chain) {
@@ -598,10 +582,10 @@
     }
 
     private FileObject getFileObject(CustomFilter cf) {
-        FileObject fo = Repository.getDefault().getDefaultFileSystem().getRoot().getFileObject(FOLDER_ID + "/" + cf.getName());
+        FileObject fo = FileUtil.getConfigRoot().getFileObject(FOLDER_ID + "/" + cf.getName());
         if (fo == null) {
             try {
-                fo = org.openide.filesystems.Repository.getDefault().getDefaultFileSystem().getRoot().getFileObject(FOLDER_ID).createData(cf.getName());
+                fo = FileUtil.getConfigRoot().getFileObject(FOLDER_ID).createData(cf.getName());
             } catch (IOException ex) {
                 Exceptions.printStackTrace(ex);
             }
@@ -610,6 +594,24 @@
     }
 
     @Override
+    public boolean requestFocus(boolean temporary) {
+        view.requestFocus();
+        return super.requestFocus(temporary);
+    }
+
+    @Override
+    protected boolean requestFocusInWindow(boolean temporary) {
+        view.requestFocus();
+        return super.requestFocusInWindow(temporary);
+    }
+
+    @Override
+    public void requestActive() {
+        super.requestActive();
+        view.requestFocus();
+    }
+
+    @Override
     public void writeExternal(ObjectOutput out) throws IOException {
         super.writeExternal(out);
 
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/Bundle.properties	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/Bundle.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -1,10 +1,7 @@
-# To change this template, choose Tools | Templates
-# and open the template in the editor.
-
-CTL_FilterAction=Open Filter Window
+CTL_FilterAction=Open Filter Window 
+CTL_MoveFilterUpAction=Move upwards
 CTL_MoveFilterDownAction=Move downwards
-CTL_MoveFilterUpAction=Move upwards
-CTL_NewFilterAction=New filter...
 CTL_RemoveFilterAction=Remove
 CTL_RemoveFilterSettingsAction=Remove filter setting
 CTL_SaveFilterSettingsAction=Save filter settings...
+CTL_NewFilterAction=New filter...
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/MoveFilterDownAction.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/MoveFilterDownAction.java	Wed Jul 27 17:32:44 2011 -0700
@@ -65,7 +65,7 @@
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/filterwindow/images/down.gif";
+        return "com/sun/hotspot/igv/filterwindow/images/down.png";
     }
 
     @Override
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/MoveFilterUpAction.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/MoveFilterUpAction.java	Wed Jul 27 17:32:44 2011 -0700
@@ -64,7 +64,7 @@
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/filterwindow/images/up.gif";
+        return "com/sun/hotspot/igv/filterwindow/images/up.png";
     }
 
     @Override
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/NewFilterAction.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/NewFilterAction.java	Wed Jul 27 17:32:44 2011 -0700
@@ -63,6 +63,6 @@
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/filterwindow/images/plus.gif";
+        return "com/sun/hotspot/igv/filterwindow/images/plus.png";
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/RemoveFilterAction.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/RemoveFilterAction.java	Wed Jul 27 17:32:44 2011 -0700
@@ -85,7 +85,7 @@
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/filterwindow/images/minus.gif";
+        return "com/sun/hotspot/igv/filterwindow/images/minus.png";
     }
 
     public HelpCtx getHelpCtx() {
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/RemoveFilterSettingsAction.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/RemoveFilterSettingsAction.java	Wed Jul 27 17:32:44 2011 -0700
@@ -63,6 +63,6 @@
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/filterwindow/images/delete.gif";
+        return "com/sun/hotspot/igv/filterwindow/images/delete.png";
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/SaveFilterSettingsAction.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/SaveFilterSettingsAction.java	Wed Jul 27 17:32:44 2011 -0700
@@ -63,6 +63,6 @@
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/filterwindow/images/add.gif";
+        return "com/sun/hotspot/igv/filterwindow/images/add.png";
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/customRightTopWsmode.xml	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/customRightTopWsmode.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -4,8 +4,8 @@
     <kind type="view" />
     <state type="joined" />
     <constraints>
-        <path orientation="horizontal" number="45" weight="0.21761006289308177"/>
-        <path orientation="vertical" number="0" weight="0.2510122989593188"/>
+        <path orientation="horizontal" number="90" weight="0.2"/>
+        <path orientation="vertical" number="0" weight="0.75"/>
     </constraints>
     <bounds x="0" y="0" width="0" height="0" />
     <frame state="0"/>
Binary file src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/add.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/add.png has changed
Binary file src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/delete.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/delete.png has changed
Binary file src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/down.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/down.png has changed
Binary file src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/minus.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/minus.png has changed
Binary file src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/plus.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/plus.png has changed
Binary file src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/up.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/up.png has changed
--- a/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/layer.xml	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/layer.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -18,8 +18,11 @@
             <attr name="position" intvalue="900"/>
         </file>
     </folder>
-    <folder name="Window">
-        <file name="com-sun-hotspot-igv-coordinator-actions-FilterAction.instance"/>
+    
+    <folder name="Actions">
+        <folder name="Window">
+            <file name="com-sun-hotspot-igv-filterwindow-actions-FilterAction.instance"/>
+        </folder>
     </folder>
     <folder name="Menu">
         <folder name="Window">
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/build.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
+<!-- for some information on what you could do (e.g. targets to override). -->
+<!-- If you delete this file and reopen the project it will be recreated. -->
+<project name="com.sun.hotspot.igv.graal" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project com.sun.hotspot.igv.graal.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/manifest.mf	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+OpenIDE-Module: com.sun.hotspot.igv.graal
+OpenIDE-Module-Layer: com/sun/hotspot/igv/graal/layer.xml
+OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/graal/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/nbproject/build-impl.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT  ***
+***         EDIT ../build.xml INSTEAD         ***
+-->
+<project name="com.sun.hotspot.igv.graal-impl" basedir="..">
+    <fail message="Please build using Ant 1.7.1 or higher.">
+        <condition>
+            <not>
+                <antversion atleast="1.7.1"/>
+            </not>
+        </condition>
+    </fail>
+    <property file="nbproject/private/suite-private.properties"/>
+    <property file="nbproject/suite.properties"/>
+    <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
+    <property file="${suite.dir}/nbproject/private/platform-private.properties"/>
+    <property file="${suite.dir}/nbproject/platform.properties"/>
+    <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="name"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{name}" value="${@{value}}"/>
+        </sequential>
+    </macrodef>
+    <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="property"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{property}" value="@{value}"/>
+        </sequential>
+    </macrodef>
+    <property file="${user.properties.file}"/>
+    <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
+        <condition>
+            <not>
+                <contains string="${cluster.path.evaluated}" substring="platform"/>
+            </not>
+        </condition>
+    </fail>
+    <import file="${harness.dir}/build.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/nbproject/genfiles.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=2bb741e3
+build.xml.script.CRC32=3534d355
+build.xml.stylesheet.CRC32=a56c6a5b@1.45.1
+# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
+# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
+nbproject/build-impl.xml.data.CRC32=2bb741e3
+nbproject/build-impl.xml.script.CRC32=2867f2d5
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.45.1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/nbproject/project.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,2 @@
+javac.source=1.5
+javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/nbproject/project.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.apisupport.project</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
+            <code-name-base>com.sun.hotspot.igv.graal</code-name-base>
+            <suite-component/>
+            <module-dependencies>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.data</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.filter</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.graph</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.graphtotext</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.structuredtext</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+            </module-dependencies>
+            <public-packages/>
+        </data>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/nbproject/suite.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,1 @@
+suite.dir=${basedir}/..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/src/META-INF/services/com.sun.hotspot.igv.graphtotext.services.GraphToTextConverter	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,1 @@
+com.sun.hotspot.igv.graal.GraalGraphToTextConverter
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/Bundle.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,1 @@
+OpenIDE-Module-Name=Graal Compiler Support
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/GraalGraphToTextConverter.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.sun.hotspot.igv.graal;
+
+import com.sun.hotspot.igv.data.InputBlock;
+import com.sun.hotspot.igv.data.InputEdge;
+import com.sun.hotspot.igv.data.InputGraph;
+import com.sun.hotspot.igv.data.InputNode;
+import com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.data.Properties.PropertyMatcher;
+import com.sun.hotspot.igv.graph.Diagram;
+import com.sun.hotspot.igv.graph.Figure;
+import com.sun.hotspot.igv.graphtotext.services.GraphToTextConverter;
+import com.sun.hotspot.igv.structuredtext.Element;
+import com.sun.hotspot.igv.structuredtext.MultiElement;
+import com.sun.hotspot.igv.structuredtext.SimpleElement;
+import com.sun.hotspot.igv.structuredtext.StructuredText;
+import java.awt.Color;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.swing.text.Style;
+import javax.swing.text.StyleConstants;
+import javax.swing.text.StyleContext;
+
+/**
+ * @author Peter Hofer
+ * @author Thomas Wuerthinger
+ */
+public class GraalGraphToTextConverter implements GraphToTextConverter {
+
+    private Map<InputNode, Set<Figure>> map;
+    private Map<InputNode, List<InputEdge>> incomingEdges;
+    private Map<InputNode, List<InputEdge>> outgoingEdges;
+    private InputGraph graph;
+
+    private Collection<InputNode> sortNodes(Collection<InputNode> nodes) {
+        List<InputNode> result = new ArrayList<InputNode>(nodes);
+        Collections.sort(result, InputNode.getPropertyComparator("idx"));
+        return result;
+    }
+
+    public StructuredText convert(InputGraph graph, Diagram diagram) {
+
+        this.graph = graph;
+        map = diagram.calcSourceToFigureRelation();
+
+        incomingEdges = graph.findAllIngoingEdges();
+        outgoingEdges = graph.findAllOutgoingEdges();
+
+        final StructuredText result = new StructuredText(graph.getName());
+
+        for (InputBlock b : graph.getBlocks()) {
+            result.addChild(new SimpleElement("Block " + b.getName() + "\n"));
+            for (InputNode n : sortNodes(b.getNodes())) {
+                result.addChild(getNodeElement(n));
+            }
+        }
+
+        boolean first = true;
+        for (InputNode n : sortNodes(graph.getNodes())) {
+            if (graph.getBlock(n) == null) {
+                if (first) {
+                    first = false;
+                    result.addChild(new SimpleElement("No block: \n"));
+                }
+                result.addChild(getNodeElement(n));
+            }
+        }
+
+        return result;
+    }
+
+    private Element getNodeNameElement(InputNode n) {
+
+        final SimpleElement name = new SimpleElement(n.getProperties().get("idx") + " " + n.getProperties().get("name"), calcStyle(n));
+        name.addSource(n.getId());
+        return name;
+    }
+
+    private Element getNodeShortElement(InputNode n) {
+        final SimpleElement id = new SimpleElement(n.getProperties().get("idx"), calcStyle(n));
+        id.addSource(n.getId());
+        return id;
+    }
+
+    private Element getNodeElement(InputNode n) {
+
+        final MultiElement result = new MultiElement();
+
+        result.print("\t");
+        result.addChild(getNodeNameElement(n));
+
+        result.print(" :::");
+
+        // NOTE: lists in ingoingEdges/outgoingEdges are sorted by from/to slot
+        //       and for slots that are connected with multiple edges, by
+        //       from/to node
+
+        int succCount = Integer.parseInt(n.getProperties().get("successorCount"));
+        InputEdge[] outgoing = outgoingEdges.get(n).toArray(new InputEdge[0]);
+
+        int i = 0;
+        if (outgoing.length > 0 && outgoing[0].getFromIndex() < succCount) {
+            // Node has successors (each connected to a different slot)
+            result.print("  Succ = [");
+            while (i < outgoing.length && outgoing[i].getFromIndex() < succCount) {
+                result.print(" ");
+                result.addChild(getNodeShortElement(graph.getNode(outgoing[i].getTo())));
+                result.print(" ");
+                i++;
+            }
+            result.print("]");
+        }
+        if (i < outgoing.length) {
+            // Node has usages (all connected to a single slot)
+            result.print("  Usages = [");
+            while (i < outgoing.length) {
+                result.print(" ");
+                result.addChild(getNodeShortElement(graph.getNode(outgoing[i].getTo())));
+                result.print(" ");
+                i++;
+            }
+            result.print("]");
+        }
+
+        int predCount = Integer.parseInt(n.getProperties().get("predecessorCount"));
+        InputEdge[] incoming = incomingEdges.get(n).toArray(new InputEdge[0]);
+
+        int j = 0;
+        if (incoming.length > 0 && incoming[0].getToIndex() < predCount) {
+            // Node has predecessors (each connected to a different slot)
+            result.print("  Pred = [");
+            while (j < incoming.length && incoming[j].getToIndex() < predCount) {
+                result.print(" ");
+                result.addChild(getNodeShortElement(graph.getNode(incoming[j].getFrom())));
+                result.print(" ");
+                j++;
+            }
+            result.print("]");
+        }
+        if (j < incoming.length) {
+            // Node has inputs (each connected to a different slot)
+            result.print("  Inputs = [");
+            while (j < incoming.length) {
+                result.print(" ");
+                result.addChild(getNodeShortElement(graph.getNode(incoming[j].getFrom())));
+                result.print(" ");
+                j++;
+            }
+            result.print("]");
+        }
+
+        result.print("\n");
+        return result;
+    }
+    private static final PropertyMatcher MATCHER = new Properties.StringPropertyMatcher("origin", "Graal");
+
+    public boolean canConvert(InputGraph graph) {
+        return graph.getGroup().getProperties().selectSingle(MATCHER) != null;
+    }
+
+    private Color calcColor(InputNode node) {
+        Set<Figure> figureSet = this.map.get(node);
+        if (figureSet != null && figureSet.size() == 1) {
+            return figureSet.iterator().next().getColor();
+        } else {
+            return Color.WHITE;
+        }
+    }
+
+    private Color lessColor(Color c) {
+        return new Color(255 - (255 - c.getRed()) / 4, 255 - (255 - c.getGreen()) / 4, 255 - (255 - c.getBlue()) / 4);
+    }
+
+    private Style calcStyle(InputNode node) {
+        Color c = calcColor(node);
+        Style defaultStyle = StyleContext.getDefaultStyleContext().getStyle(StyleContext.DEFAULT_STYLE);
+        Style newStyle = StyleContext.getDefaultStyleContext().addStyle(null, defaultStyle);
+
+        StyleConstants.setBackground(newStyle, lessColor(c));
+        return newStyle;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalColoringFilter.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,79 @@
+/*
+ * 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.sun.hotspot.igv.graal.filters;
+
+import com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.filter.AbstractFilter;
+import com.sun.hotspot.igv.graph.Diagram;
+import com.sun.hotspot.igv.graph.Figure;
+import java.awt.Color;
+import java.util.List;
+
+public class GraalColoringFilter extends AbstractFilter {
+    
+    private String colorName;
+
+    public GraalColoringFilter(String colorName) {
+        this.colorName = colorName;
+    }
+
+    public String getName() {
+        return "Graal Coloring Filter (" + colorName + ")";
+    }
+
+    public void apply(Diagram d) {
+        List<Figure> figures = d.getFigures();
+        int colors = 0;
+        for (Figure f : figures) {
+            Properties p = f.getProperties();
+            final String prop = p.get(colorName + "Color");
+            if (prop == null) {
+                continue;
+            }
+            try {
+                int color = Integer.parseInt(prop);
+                if (color > colors) {
+                    colors = color;
+                }
+            } catch (NumberFormatException nfe) {
+                // nothing to do
+            }
+        }
+        colors++;
+        for (Figure f : figures) {
+            Properties p = f.getProperties();
+            final String prop = p.get(colorName + "Color");
+            if (prop == null) {
+                continue;
+            }
+            try {
+                int color = Integer.parseInt(prop);
+                Color c = Color.getHSBColor((float) color / colors, 1.0f, 0.7f);
+                f.setColor(c);
+            } catch (NumberFormatException nfe) {
+                // nothing to do
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalEdgeColorFilter.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,114 @@
+/*
+ * 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.sun.hotspot.igv.graal.filters;
+
+import com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.filter.AbstractFilter;
+import com.sun.hotspot.igv.graph.Connection;
+import com.sun.hotspot.igv.graph.Diagram;
+import com.sun.hotspot.igv.graph.Figure;
+import com.sun.hotspot.igv.graph.InputSlot;
+import com.sun.hotspot.igv.graph.OutputSlot;
+import java.awt.Color;
+import java.util.List;
+
+/**
+ * Filter that colors usage and successor edges differently.
+ * 
+ * @author Peter Hofer
+ */
+public class GraalEdgeColorFilter extends AbstractFilter {
+
+    private Color successorColor = Color.BLUE;
+    private Color usageColor = Color.RED;
+    private Color memoryColor = Color.GREEN;
+
+    public GraalEdgeColorFilter() {
+    }
+
+    public String getName() {
+        return "Graal Edge Color Filter";
+    }
+
+    public void apply(Diagram d) {
+        List<Figure> figures = d.getFigures();
+        for (Figure f : figures) {
+            Properties p = f.getProperties();
+            int succCount = Integer.parseInt(p.get("successorCount"));
+            for (OutputSlot os : f.getOutputSlots()) {
+                Color color;
+                if (os.getPosition() < succCount) {
+                    color = successorColor;
+                } else {
+                    color = usageColor;
+                }
+
+                os.setColor(color);
+                for (Connection c : os.getConnections()) {
+                    c.setColor(color);
+                }
+            }
+        }
+        for (Figure f : figures) {
+            Properties p = f.getProperties();
+            int predCount = Integer.parseInt(p.get("predecessorCount"));
+            int inputCount = Integer.parseInt(p.get("inputCount"));
+            int variableInputCount = Integer.parseInt(p.get("variableInputCount"));
+            if (p.get("memoryCheckpoint") != null) {
+                for (InputSlot is : f.getInputSlots()) {
+                    if (is.getPosition() > predCount + inputCount - variableInputCount) {
+                        is.setColor(memoryColor);
+                        for (Connection c : is.getConnections()) {
+                            c.setColor(memoryColor);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    public Color getUsageColor() {
+        return usageColor;
+    }
+
+    public void setUsageColor(Color usageColor) {
+        this.usageColor = usageColor;
+    }
+    
+    public void setMemoryColor(Color memoryColor) {
+        this.memoryColor = memoryColor;
+    }
+
+    public Color getMemoryColor() {
+        return memoryColor;
+    }
+    
+    public Color getSuccessorColor() {
+        return successorColor;
+    }
+
+    public void setSuccessorColor(Color successorColor) {
+        this.successorColor = successorColor;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/color.filter	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,11 @@
+colorize("name", ".*", white);
+colorize("name", "StartNode|EndNode|LoopBegin|LoopEnd|Return", orange);
+colorize("name", "Phi:.*", magenta);
+colorize("name", "FrameState@.*", new java.awt.Color(0.5, 0.8, 1.0));
+colorize("name", "If", pink);
+colorize("name", "const.*", new java.awt.Color(0.7, 0.7, 0.7));
+colorize("name", "Local", new java.awt.Color(0.85, 0.85, 0.85));
+colorize("name", "\\+|-|\\*|/", cyan);
+colorize("name", "Comp .*", yellow);
+
+colorize("notInOwnBlock", "true", red);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/edgeColor.filter	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,4 @@
+var f = new com.sun.hotspot.igv.graal.filters.GraalEdgeColorFilter();
+f.setUsageColor(blue);
+f.setSuccessorColor(red);
+f.apply(graph);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/probability.filter	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,3 @@
+colorizeGradientWithMode("probability", 0, 500, "logarithmic");
+
+// more parameters: colorizeGradientCustom("probability", 0, 500, "logarithmic", [blue, yellow, red], [0, 0.5, 1], 16);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/slots.filter	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,1 @@
+removeUnconnectedSlots(true, true);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/layer.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd">
+<filesystem>
+    <folder name="Filters">
+        <file name="Graal Coloring" url="filters/color.filter">
+            <attr name="enabled" boolvalue="false"/>
+        </file>
+        
+        <file name="Graal Edge Coloring" url="filters/edgeColor.filter">
+            <attr name="enabled" boolvalue="false"/>
+        </file>
+        
+        <file name="Graal Slot Filter" url="filters/slots.filter">
+            <attr name="enabled" boolvalue="false"/>
+        </file>
+        
+        <file name="Graal Probability Filter" url="filters/probability.filter">
+            <attr name="enabled" boolvalue="false"/>
+        </file>
+    </folder>
+</filesystem>
--- a/src/share/tools/IdealGraphVisualizer/Graph/nbproject/project.xml	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Graph/nbproject/project.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -25,6 +25,7 @@
             </module-dependencies>
             <public-packages>
                 <package>com.sun.hotspot.igv.graph</package>
+                <package>com.sun.hotspot.igv.graph.services</package>
             </public-packages>
         </data>
     </configuration>
--- a/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Block.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Block.java	Wed Jul 27 17:32:44 2011 -0700
@@ -60,14 +60,6 @@
         return succs;
     }
 
-    public Set<? extends Cluster> getPredecessors() {
-        Set<Block> succs = new HashSet<Block>();
-        for (InputBlock b : inputBlock.getPredecessors()) {
-            succs.add(diagram.getBlock(b));
-        }
-        return succs;
-    }
-
     public void setBounds(Rectangle r) {
         this.bounds = r;
     }
@@ -79,4 +71,10 @@
     public int compareTo(Cluster o) {
         return toString().compareTo(o.toString());
     }
+
+    @Override
+    public String toString() {
+        return inputBlock.getName();
+    }
 }
+    
--- a/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Connection.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Connection.java	Wed Jul 27 17:32:44 2011 -0700
@@ -23,6 +23,7 @@
  */
 package com.sun.hotspot.igv.graph;
 
+import com.sun.hotspot.igv.data.Source;
 import com.sun.hotspot.igv.layout.Link;
 import com.sun.hotspot.igv.layout.Port;
 import java.awt.Color;
@@ -31,7 +32,7 @@
 import java.util.List;
 
 /**
- *
+ * 
  * @author Thomas Wuerthinger
  */
 public class Connection implements Source.Provider, Link {
@@ -99,6 +100,10 @@
         outputSlot.getFigure().removeSuccessor(inputSlot.getFigure());
         outputSlot.connections.remove(this);
     }
+    
+    public String getToolTipText() {
+        return "From " + this.getOutputSlot().getFigure().toString() + " to " + this.getInputSlot().getFigure();
+    }
 
     @Override
     public String toString() {
@@ -121,3 +126,4 @@
         controlPoints = list;
     }
 }
+
--- a/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Diagram.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Diagram.java	Wed Jul 27 17:32:44 2011 -0700
@@ -28,6 +28,7 @@
 import com.sun.hotspot.igv.data.InputGraph;
 import com.sun.hotspot.igv.data.InputNode;
 import com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.data.Properties.StringPropertyMatcher;
 import java.awt.Font;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -35,7 +36,8 @@
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -52,19 +54,26 @@
     private int curId;
     private String nodeText;
     private Font font;
+    private Font slotFont;
 
     public Font getFont() {
         return font;
     }
 
+    public Font getSlotFont() {
+        return slotFont;
+    }
+    
     private Diagram() {
         figures = new ArrayList<Figure>();
-        blocks = new HashMap<InputBlock, Block>();
+        blocks = new LinkedHashMap<InputBlock, Block>(8);
         this.nodeText = "";
-        this.font = new Font("Serif", Font.PLAIN, 14);
+        this.font = new Font("Arial", Font.PLAIN, 13);
+        this.slotFont = new Font("Arial", Font.PLAIN, 10);
     }
 
     public Block getBlock(InputBlock b) {
+        assert blocks.containsKey(b);
         return blocks.get(b);
     }
 
@@ -72,12 +81,7 @@
         return nodeText;
     }
 
-    public void schedule(Collection<InputBlock> newBlocks) {
-        graph.schedule(newBlocks);
-        updateBlocks();
-    }
-
-    private void updateBlocks() {
+    public void updateBlocks() {
         blocks.clear();
         for (InputBlock b : graph.getBlocks()) {
             Block curBlock = new Block(b, this);
@@ -113,6 +117,22 @@
         assert outputSlot.getFigure().getDiagram() == this;
         return new Connection(inputSlot, outputSlot);
     }
+    
+    public Map<InputNode, Set<Figure>> calcSourceToFigureRelation() {
+        Map<InputNode, Set<Figure>> map = new HashMap<InputNode, Set<Figure>>();
+        
+        for(InputNode node : this.getGraph().getNodes()) {
+            map.put(node, new HashSet<Figure>());
+        }
+        
+        for(Figure f : this.getFigures()) {
+            for(InputNode node : f.getSource().getSourceNodes()) {
+                map.get(node).add(f);
+            }
+        }
+        
+        return map;
+    }
 
     public static Diagram createDiagram(InputGraph graph, String nodeText) {
         if (graph == null) {
@@ -126,7 +146,7 @@
         d.updateBlocks();
 
         Collection<InputNode> nodes = graph.getNodes();
-        HashMap<Integer, Figure> figureHash = new HashMap<Integer, Figure>();
+        Hashtable<Integer, Figure> figureHash = new Hashtable<Integer, Figure>();
         for (InputNode n : nodes) {
             Figure f = d.createFigure();
             f.getSource().addSourceNode(n);
@@ -141,19 +161,19 @@
             Figure fromFigure = figureHash.get(from);
             Figure toFigure = figureHash.get(to);
             assert fromFigure != null && toFigure != null;
+            
+            if(fromFigure == null || toFigure == null) continue;
+
+            int fromIndex = e.getFromIndex();
+            while (fromFigure.getOutputSlots().size() <= fromIndex) {
+                fromFigure.createOutputSlot();
+            }
+            OutputSlot outputSlot = fromFigure.getOutputSlots().get(fromIndex);
 
             int toIndex = e.getToIndex();
-
-            while (fromFigure.getOutputSlots().size() <= 0) {
-                fromFigure.createOutputSlot();
-            }
-
-            OutputSlot outputSlot = fromFigure.getOutputSlots().get(0);
-
             while (toFigure.getInputSlots().size() <= toIndex) {
                 toFigure.createInputSlot();
             }
-
             InputSlot inputSlot = toFigure.getInputSlots().get(toIndex);
 
             Connection c = d.createConnection(inputSlot, outputSlot);
@@ -232,9 +252,9 @@
 
     public Figure getRootFigure() {
         Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<Figure>(figures);
-        Figure root = selector.selectSingle("name", "Root");
+        Figure root = selector.selectSingle(new StringPropertyMatcher("name", "Root"));
         if (root == null) {
-            root = selector.selectSingle("name", "Start");
+            root = selector.selectSingle(new StringPropertyMatcher("name", "Start"));
         }
         if (root == null) {
             List<Figure> rootFigures = getRootFigures();
--- a/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Figure.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Figure.java	Wed Jul 27 17:32:44 2011 -0700
@@ -23,16 +23,21 @@
  */
 package com.sun.hotspot.igv.graph;
 
+import com.sun.hotspot.igv.data.InputBlock;
+import com.sun.hotspot.igv.data.Source;
+import com.sun.hotspot.igv.data.InputNode;
 import com.sun.hotspot.igv.layout.Cluster;
 import com.sun.hotspot.igv.layout.Vertex;
 import com.sun.hotspot.igv.data.Properties;
 import java.awt.Color;
 import java.awt.Dimension;
+import java.awt.Font;
 import java.awt.FontMetrics;
 import java.awt.Graphics;
 import java.awt.Point;
 import java.awt.image.BufferedImage;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
@@ -44,9 +49,11 @@
  */
 public class Figure extends Properties.Entity implements Source.Provider, Vertex {
 
-    public static final int INSET = 6;
-    public static final int SLOT_WIDTH = 10;
-    public static final int SLOT_START = 3;
+    public static final int INSET = 12;
+    public static int SLOT_WIDTH = 12;
+    public static final int OVERLAPPING = 6;
+    public static final int SLOT_START = 4;
+    public static final int SLOT_OFFSET = 8;
     public static final boolean VERTICAL_LAYOUT = true;
     protected List<InputSlot> inputSlots;
     protected List<OutputSlot> outputSlots;
@@ -66,28 +73,49 @@
         if (heightCash == -1) {
             BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
             Graphics g = image.getGraphics();
-            g.setFont(diagram.getFont());
+            g.setFont(diagram.getFont().deriveFont(Font.BOLD));
             FontMetrics metrics = g.getFontMetrics();
             String nodeText = diagram.getNodeText();
             heightCash = nodeText.split("\n").length * metrics.getHeight() + INSET;
         }
         return heightCash;
     }
+    
+    public static <T> List<T> getAllBefore(List<T> inputList, T tIn) {
+        List<T> result = new ArrayList<T>();
+        for(T t : inputList) {
+            if(t.equals(tIn)) {
+                break;
+            }
+            result.add(t);
+        }
+        return result;
+    }
+    
+    public static int getSlotsWidth(Collection<? extends Slot> slots) {
+        int result = Figure.SLOT_OFFSET;
+        for(Slot s : slots) {
+            result += s.getWidth() + Figure.SLOT_OFFSET;
+        }
+        return result;
+    }
 
     public int getWidth() {
         if (widthCash == -1) {
             int max = 0;
             BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
             Graphics g = image.getGraphics();
-            g.setFont(diagram.getFont());
+            g.setFont(diagram.getFont().deriveFont(Font.BOLD));
             FontMetrics metrics = g.getFontMetrics();
-            for (String s : lines) {
+            for (String s : getLines()) {
                 int cur = metrics.stringWidth(s);
                 if (cur > max) {
                     max = cur;
                 }
             }
             widthCash = max + INSET;
+            widthCash = Math.max(widthCash, Figure.getSlotsWidth(inputSlots));
+            widthCash = Math.max(widthCash, Figure.getSlotsWidth(outputSlots));
         }
         return widthCash;
     }
@@ -221,6 +249,13 @@
     public List<InputSlot> getInputSlots() {
         return Collections.unmodifiableList(inputSlots);
     }
+    
+    public Set<Slot> getSlots() {
+        Set<Slot> result = new HashSet<Slot>();
+        result.addAll(getInputSlots());
+        result.addAll(getOutputSlots());
+        return result;
+    }
 
     public List<OutputSlot> getOutputSlots() {
         return Collections.unmodifiableList(outputSlots);
@@ -248,13 +283,13 @@
         String[] result = new String[strings.length];
 
         for (int i = 0; i < strings.length; i++) {
-            result[i] = resolveString(strings[i]);
+            result[i] = resolveString(strings[i], getProperties());
         }
 
         lines = result;
     }
 
-    private String resolveString(String string) {
+    public static final String resolveString(String string, Properties properties) {
 
         StringBuilder sb = new StringBuilder();
         boolean inBrackets = false;
@@ -264,7 +299,7 @@
             char c = string.charAt(i);
             if (inBrackets) {
                 if (c == ']') {
-                    String value = getProperties().get(curIdent.toString());
+                    String value = properties.get(curIdent.toString());
                     if (value == null) {
                         value = "";
                     }
@@ -289,10 +324,12 @@
     public Dimension getSize() {
         if (VERTICAL_LAYOUT) {
             int width = Math.max(getWidth(), Figure.SLOT_WIDTH * (Math.max(inputSlots.size(), outputSlots.size()) + 1));
-            int height = getHeight() + 2 * Figure.SLOT_WIDTH;
+            int height = getHeight() + 2 * Figure.SLOT_WIDTH - 2 * Figure.OVERLAPPING;
+            
+            
             return new Dimension(width, height);
         } else {
-            int width = getWidth() + 2 * Figure.SLOT_WIDTH;
+            int width = getWidth() + 2 * Figure.SLOT_WIDTH - 2*Figure.OVERLAPPING;
             int height = Figure.SLOT_WIDTH * (Math.max(inputSlots.size(), outputSlots.size()) + 1);
             return new Dimension(width, height);
         }
@@ -308,15 +345,19 @@
             assert false : "Should never reach here, every figure must have at least one source node!";
             return null;
         } else {
-            Cluster result = diagram.getBlock(diagram.getGraph().getBlock(getSource().getSourceNodes().get(0)));
+            final InputBlock inputBlock = diagram.getGraph().getBlock(getSource().getSourceNodes().get(0));
+            assert inputBlock != null;
+            Cluster result = diagram.getBlock(inputBlock);
             assert result != null;
             return result;
         }
     }
 
     public boolean isRoot() {
-        if (source.getSourceNodes().size() > 0 && source.getSourceNodes().get(0).getProperties().get("name").equals("Root")) {
-            return true;
+  
+        List<InputNode> sourceNodes = source.getSourceNodes();
+        if (sourceNodes.size() > 0 && sourceNodes.get(0).getProperties().get("name") != null) {
+            return source.getSourceNodes().get(0).getProperties().get("name").equals("Root");
         } else {
             return false;
         }
--- a/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/InputSlot.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/InputSlot.java	Wed Jul 27 17:32:44 2011 -0700
@@ -27,7 +27,7 @@
 import java.util.List;
 
 /**
- *
+ * 
  * @author Thomas Wuerthinger
  */
 public class InputSlot extends Slot {
@@ -45,9 +45,12 @@
         InputSlot s = inputSlots.remove(position);
         inputSlots.add(position, s);
     }
-
     public Point getRelativePosition() {
-        return new Point(getFigure().getWidth() * (getPosition() + 1) / (getFigure().getInputSlots().size() + 1), Figure.SLOT_WIDTH - Figure.SLOT_START);
+        int gap = getFigure().getWidth() - Figure.getSlotsWidth(getFigure().getInputSlots());
+        double gapRatio = (double)gap / (double)(getFigure().getInputSlots().size() + 1);
+        int gapAmount = (int)((getPosition() + 1)*gapRatio);
+        return new Point(gapAmount + Figure.getSlotsWidth(Figure.getAllBefore(getFigure().getInputSlots(), this)) + getWidth()/2, -Figure.SLOT_START);
+        //return new Point((getFigure().getWidth() / (getFigure().getInputSlots().size() * 2)) * (getPosition() * 2 + 1), -Figure.SLOT_START);
     }
 
     @Override
--- a/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/OutputSlot.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/OutputSlot.java	Wed Jul 27 17:32:44 2011 -0700
@@ -26,7 +26,7 @@
 import java.awt.Point;
 
 /**
- *
+ * 
  * @author Thomas Wuerthinger
  */
 public class OutputSlot extends Slot {
@@ -45,7 +45,13 @@
     }
 
     public Point getRelativePosition() {
-        return new Point(getFigure().getWidth() * (getPosition() + 1) / (getFigure().getOutputSlots().size() + 1), getFigure().getSize().height - Figure.SLOT_WIDTH + Figure.SLOT_START);
+        int gap = getFigure().getWidth() - Figure.getSlotsWidth(getFigure().getOutputSlots());
+        if(gap < 0) {
+            gap = 0;
+        }
+        double gapRatio = (double)gap / (double)(getFigure().getOutputSlots().size() + 1);
+        int gapAmount = (int)((getPosition() + 1)*gapRatio);
+        return new Point(gapAmount + Figure.getSlotsWidth(Figure.getAllBefore(getFigure().getOutputSlots(), this)) + getWidth()/2, Figure.SLOT_START);
     }
 
     @Override
--- a/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Slot.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Slot.java	Wed Jul 27 17:32:44 2011 -0700
@@ -23,103 +23,168 @@
  */
 package com.sun.hotspot.igv.graph;
 
+import com.sun.hotspot.igv.data.InputNode;
+import com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.data.Source;
 import com.sun.hotspot.igv.layout.Port;
 import com.sun.hotspot.igv.layout.Vertex;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.image.BufferedImage;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Comparator;
 
 /**
- *
+ * 
  * @author Thomas Wuerthinger
  */
-public abstract class Slot implements Port, Source.Provider {
-
-    private int wantedIndex;
-    private String name;
-    private String shortName; // 1 - 2 characters
-    private Source source;
-    protected List<Connection> connections;
-    private Figure figure;
+public abstract class Slot implements Port, Source.Provider, Properties.Provider {
 
-    protected Slot(Figure figure, int wantedIndex) {
-        this.figure = figure;
-        connections = new ArrayList<Connection>(2);
-        source = new Source();
-        this.wantedIndex = wantedIndex;
-        name = "";
-        shortName = "";
-        assert figure != null;
-    }
-    public static final Comparator<Slot> slotIndexComparator = new Comparator<Slot>() {
+	private int wantedIndex;
+	private Source source;
+	protected List<Connection> connections;
+	private InputNode associatedNode;
+	private Color color;
+	private String text;
+	private String shortName;
+	private Figure figure;
+
+	protected Slot(Figure figure, int wantedIndex) {
+		this.figure = figure;
+		connections = new ArrayList<Connection>(2);
+		source = new Source();
+		this.wantedIndex = wantedIndex;
+		text = "";
+		shortName = "";
+		assert figure != null;
+	}
 
-        public int compare(Slot o1, Slot o2) {
-            return o1.wantedIndex - o2.wantedIndex;
-        }
-    };
-    public static final Comparator<Slot> slotFigureComparator = new Comparator<Slot>() {
+	public Properties getProperties() {
+		Properties p = new Properties();
+		if (source.getSourceNodes().size() > 0) {
+			for (InputNode n : source.getSourceNodes()) {
+				p.add(n.getProperties());
+			}
+		} else {
+			p.setProperty("name", "Slot");
+			p.setProperty("figure", figure.getProperties().get("name"));
+			p.setProperty("connectionCount", Integer.toString(connections.size()));
+		}
+		return p;
+	}
+	public static final Comparator<Slot> slotIndexComparator = new Comparator<Slot>() {
 
-        public int compare(Slot o1, Slot o2) {
-            return o1.figure.getId() - o2.figure.getId();
-        }
-    };
+		public int compare(Slot o1, Slot o2) {
+			return o1.wantedIndex - o2.wantedIndex;
+		}
+	};
+	public static final Comparator<Slot> slotFigureComparator = new Comparator<Slot>() {
 
-    public int getWantedIndex() {
-        return wantedIndex;
-    }
+		public int compare(Slot o1, Slot o2) {
+			return o1.figure.getId() - o2.figure.getId();
+		}
+	};
+
+	public InputNode getAssociatedNode() {
+		return associatedNode;
+	}
+
+	public void setAssociatedNode(InputNode node) {
+		associatedNode = node;
+	}
 
-    public Source getSource() {
-        return source;
-    }
+	public int getWidth() {
+		if (shortName == null || shortName.length() <= 1) {
+			return Figure.SLOT_WIDTH;
+		} else {
+			BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
+			Graphics g = image.getGraphics();
+			g.setFont(figure.getDiagram().getSlotFont().deriveFont(Font.BOLD));
+			FontMetrics metrics = g.getFontMetrics();
+			return Math.max(Figure.SLOT_WIDTH, metrics.stringWidth(shortName) + 6);
+		}
+	}
 
-    public String getName() {
-        return name;
-    }
+	public int getWantedIndex() {
+		return wantedIndex;
+	}
 
-    public void setShortName(String s) {
-        assert s != null;
-        assert s.length() <= 2;
-        this.shortName = s;
+	public Source getSource() {
+		return source;
+	}
 
-    }
+	public String getText() {
+		return text;
+	}
 
-    public String getShortName() {
-        return shortName;
-    }
+	public void setShortName(String s) {
+		assert s != null;
+//        assert s.length() <= 2;
+		this.shortName = s;
+
+	}
 
-    public boolean getShowName() {
-        return getShortName() != null && getShortName().length() > 0;
-    }
+	public String getShortName() {
+		return shortName;
+	}
+
+	public String getToolTipText() {
+		StringBuilder sb = new StringBuilder();
+		sb.append(text);
 
-    public void setName(String s) {
-        if (s == null) {
-            s = "";
-        }
-        this.name = s;
-    }
+		for (InputNode n : getSource().getSourceNodes()) {
+			sb.append("Node (ID=" + n.getId() + "): " + n.getProperties().get("name"));
+			sb.append("<br>");
+		}
+
+		return sb.toString();
+	}
+
+	public boolean shouldShowName() {
+		return getShortName() != null && getShortName().length() > 0;
+	}
 
-    public Figure getFigure() {
-        assert figure != null;
-        return figure;
-    }
+	public void setText(String s) {
+		if (s == null) {
+			s = "";
+		}
+		this.text = s;
+	}
 
-    public List<Connection> getConnections() {
-        return Collections.unmodifiableList(connections);
-    }
+	public Figure getFigure() {
+		assert figure != null;
+		return figure;
+	}
+
+	public Color getColor() {
+		return this.color;
+	}
+
+	public void setColor(Color c) {
+		color = c;
+	}
 
-    public void removeAllConnections() {
-        List<Connection> connectionsCopy = new ArrayList<Connection>(this.connections);
-        for (Connection c : connectionsCopy) {
-            c.remove();
-        }
-    }
+	public List<Connection> getConnections() {
+		return Collections.unmodifiableList(connections);
+	}
 
-    public Vertex getVertex() {
-        return figure;
-    }
+	public void removeAllConnections() {
+		List<Connection> connectionsCopy = new ArrayList<Connection>(this.connections);
+		for (Connection c : connectionsCopy) {
+			c.remove();
+		}
+	}
 
-    public abstract int getPosition();
+	public Vertex getVertex() {
+		return figure;
+	}
 
-    public abstract void setPosition(int position);
+	public abstract int getPosition();
+
+	public abstract void setPosition(int position);
 }
+
--- a/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Source.java	Tue Jun 28 10:57:38 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-/*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-package com.sun.hotspot.igv.graph;
-
-import com.sun.hotspot.igv.data.InputBlock;
-import com.sun.hotspot.igv.data.InputGraph;
-import com.sun.hotspot.igv.data.InputNode;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public class Source {
-
-    private List<InputNode> sourceNodes;
-    private Set<Integer> set;
-
-    public Source() {
-        sourceNodes = new ArrayList<InputNode>(1);
-    }
-
-    public List<InputNode> getSourceNodes() {
-        return Collections.unmodifiableList(sourceNodes);
-    }
-
-    public Set<Integer> getSourceNodesAsSet() {
-        if (set == null) {
-            set = new HashSet<Integer>();
-            for (InputNode n : sourceNodes) {
-                int id = n.getId();
-                //if(id < 0) id = -id;
-                set.add(id);
-            }
-        }
-        return set;
-    }
-
-    public void addSourceNode(InputNode n) {
-        sourceNodes.add(n);
-        set = null;
-    }
-
-    public void removeSourceNode(InputNode n) {
-        sourceNodes.remove(n);
-        set = null;
-    }
-
-    public interface Provider {
-
-        public Source getSource();
-    }
-
-    public void setSourceNodes(List<InputNode> sourceNodes) {
-        this.sourceNodes = sourceNodes;
-        set = null;
-    }
-
-    public void addSourceNodes(Source s) {
-        for (InputNode n : s.getSourceNodes()) {
-            sourceNodes.add(n);
-        }
-        set = null;
-    }
-
-    public boolean isInBlock(InputGraph g, InputBlock blockNode) {
-
-        for (InputNode n : this.getSourceNodes()) {
-            if (g.getBlock(n) == blockNode) {
-                return true;
-            }
-        }
-        return false;
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/services/DiagramProvider.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package com.sun.hotspot.igv.graph.services;
+
+import com.sun.hotspot.igv.data.ChangedEvent;
+import com.sun.hotspot.igv.graph.Diagram;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public interface DiagramProvider {
+    Diagram getDiagram();
+    ChangedEvent<DiagramProvider> getChangedEvent();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/GraphTextEditor/build.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
+<!-- for some information on what you could do (e.g. targets to override). -->
+<!-- If you delete this file and reopen the project it will be recreated. -->
+<project name="com.sun.hotspot.igv.graphtexteditor" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project com.sun.hotspot.igv.graphtexteditor.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/GraphTextEditor/manifest.mf	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+OpenIDE-Module: com.sun.hotspot.igv.graphtexteditor
+OpenIDE-Module-Layer: com/sun/hotspot/igv/graphtexteditor/layer.xml
+OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/graphtexteditor/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/GraphTextEditor/nbproject/build-impl.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT  ***
+***         EDIT ../build.xml INSTEAD         ***
+-->
+<project name="com.sun.hotspot.igv.graphtexteditor-impl" basedir="..">
+    <fail message="Please build using Ant 1.7.1 or higher.">
+        <condition>
+            <not>
+                <antversion atleast="1.7.1"/>
+            </not>
+        </condition>
+    </fail>
+    <property file="nbproject/private/suite-private.properties"/>
+    <property file="nbproject/suite.properties"/>
+    <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
+    <property file="${suite.dir}/nbproject/private/platform-private.properties"/>
+    <property file="${suite.dir}/nbproject/platform.properties"/>
+    <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="name"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{name}" value="${@{value}}"/>
+        </sequential>
+    </macrodef>
+    <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="property"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{property}" value="@{value}"/>
+        </sequential>
+    </macrodef>
+    <property file="${user.properties.file}"/>
+    <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
+        <condition>
+            <not>
+                <contains string="${cluster.path.evaluated}" substring="platform"/>
+            </not>
+        </condition>
+    </fail>
+    <import file="${harness.dir}/build.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/GraphTextEditor/nbproject/genfiles.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,5 @@
+# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
+# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
+nbproject/build-impl.xml.data.CRC32=f0880ef0
+nbproject/build-impl.xml.script.CRC32=9388e04e
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.45.1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/GraphTextEditor/nbproject/project.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,2 @@
+javac.source=1.5
+javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/GraphTextEditor/nbproject/project.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.apisupport.project</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
+            <code-name-base>com.sun.hotspot.igv.graphtexteditor</code-name-base>
+            <suite-component/>
+            <module-dependencies>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.data</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.graph</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.graphtotext</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.selectioncoordinator</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.structuredtext</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.texteditor</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.util</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.diff</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.32.1.42.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.12.0.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.lookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.6.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.windows</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>6.20</specification-version>
+                    </run-dependency>
+                </dependency>
+            </module-dependencies>
+            <public-packages/>
+        </data>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/GraphTextEditor/nbproject/suite.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,1 @@
+suite.dir=${basedir}/..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/GraphTextEditor/src/com/sun/hotspot/igv/graphtexteditor/Bundle.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,4 @@
+CTL_TextAction=Open Text Window
+CTL_TextTopComponent=Text
+HINT_TextTopComponent=Shows a textual representation of the graph.
+OpenIDE-Module-Name=GraphTextEditor
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/GraphTextEditor/src/com/sun/hotspot/igv/graphtexteditor/TextAction.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package com.sun.hotspot.igv.graphtexteditor;
+
+import java.awt.event.ActionEvent;
+import javax.swing.AbstractAction;
+import org.openide.util.NbBundle;
+import org.openide.windows.TopComponent;
+
+/**
+ * Action which shows Text component.
+ */
+public class TextAction extends AbstractAction {
+
+    public TextAction() {
+        super(NbBundle.getMessage(TextAction.class, "CTL_TextAction"));
+
+        System.out.println("Text action initialized!!!");
+//        putValue(SMALL_ICON, new ImageIcon(Utilities.loadImage(TextTopComponent.ICON_PATH, true)));
+    }
+
+    public void actionPerformed(ActionEvent evt) {
+        TopComponent win = TextTopComponent.findInstance();
+        win.open();
+        win.requestActive();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/GraphTextEditor/src/com/sun/hotspot/igv/graphtexteditor/TextTopComponent.form	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,18 @@
+<?xml version="1.1" encoding="UTF-8" ?>
+
+<Form version="1.4" maxVersion="1.6" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+  <AuxValues>
+    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+    <AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
+  </AuxValues>
+
+  <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
+</Form>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/GraphTextEditor/src/com/sun/hotspot/igv/graphtexteditor/TextTopComponent.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,434 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.graphtexteditor;
+
+import com.sun.hotspot.igv.data.ChangedListener;
+import com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.texteditor.*;
+import com.sun.hotspot.igv.data.InputGraph;
+import com.sun.hotspot.igv.data.Pair;
+import com.sun.hotspot.igv.data.Property;
+import com.sun.hotspot.igv.graph.Diagram;
+import com.sun.hotspot.igv.graph.services.DiagramProvider;
+import com.sun.hotspot.igv.graphtotext.services.GraphToTextConverter;
+import com.sun.hotspot.igv.selectioncoordinator.SelectionCoordinator;
+import com.sun.hotspot.igv.structuredtext.MultiElement;
+import com.sun.hotspot.igv.structuredtext.StructuredText;
+import com.sun.hotspot.igv.util.LookupHistory;
+import java.awt.BorderLayout;
+import java.awt.CardLayout;
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.io.IOException;
+import java.io.Serializable;
+import java.io.StringReader;
+import java.util.Collection;
+import java.util.logging.Logger;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JSplitPane;
+import javax.swing.JToolBar;
+import org.netbeans.api.diff.Diff;
+import org.netbeans.api.diff.DiffView;
+import org.netbeans.api.diff.StreamSource;
+import org.openide.util.Lookup;
+import org.openide.util.LookupEvent;
+import org.openide.util.LookupListener;
+import org.openide.util.NbBundle;
+import org.openide.util.Utilities;
+import org.openide.windows.TopComponent;
+import org.openide.windows.WindowManager;
+
+/**
+ * @author Thomas Wuerthinger
+ * @author Peter Hofer
+ */
+final class TextTopComponent extends TopComponent implements LookupListener {
+
+    private static TextTopComponent instance;
+    private Lookup.Result result = null;
+    private static final String PREFERRED_ID = "TextTopComponent";
+    private Diagram lastDiagram;
+    private TextEditor leftEditor;
+    private TextEditor rightEditor;
+    private TextEditor singleEditor;
+    private JSplitPane splitPane;
+    private CardLayout cardLayout;
+    private JPanel cardLayoutPanel;
+    private JComboBox sourceCombo;
+    private boolean firstTimeSplitter = true;
+    private JPanel textDiffPanel;
+
+    private static final String TWO_GRAPHS_TEXT_DIFF = "twoGraphsTextDiff";
+    private static final String TWO_GRAPHS = "twoGraphs";
+    private static final String ONE_GRAPH = "oneGraph";
+    private static final String NO_GRAPH = "noGraph";
+
+    private static final String GRAPH_TEXT_REPRESENTATION = "< Graph Text Representation >";
+
+    private DiagramProvider currentDiagramProvider;
+
+    private TextTopComponent() {
+        initComponents();
+        setName(NbBundle.getMessage(TextTopComponent.class, "CTL_TextTopComponent"));
+        setToolTipText(NbBundle.getMessage(TextTopComponent.class, "HINT_TextTopComponent"));
+
+        setLayout(new BorderLayout());
+
+        // Selector for displayed data
+        JToolBar sourceSelectBar = new JToolBar();
+        sourceSelectBar.setLayout(new BorderLayout());
+        sourceSelectBar.setFloatable(false);
+        sourceSelectBar.add(new JLabel("Show: "), BorderLayout.WEST);
+        sourceCombo = new JComboBox();
+        sourceCombo.addItem(GRAPH_TEXT_REPRESENTATION);
+        sourceCombo.addItemListener(sourceSelectionListener);
+        sourceSelectBar.add(sourceCombo, BorderLayout.CENTER);
+        add(sourceSelectBar, BorderLayout.NORTH);
+
+        // Card layout for three different views.
+        cardLayout = new CardLayout();
+        cardLayoutPanel = new JPanel(cardLayout);
+        add(cardLayoutPanel, BorderLayout.CENTER);
+
+        // No graph selected.
+        JLabel noGraphLabel = new JLabel("No graph open.", JLabel.CENTER);
+        noGraphLabel.setOpaque(true);
+        noGraphLabel.setBackground(Color.WHITE);
+        cardLayoutPanel.add(noGraphLabel, NO_GRAPH);
+
+        // Single graph selected.
+        singleEditor = new TextEditor();
+        cardLayoutPanel.add(singleEditor.getComponent(), ONE_GRAPH);
+
+        // Graph difference => show split pane with two graphs.
+        splitPane = new JSplitPane();
+        leftEditor = new TextEditor();
+        rightEditor = new TextEditor();
+        // Work around a problem with JSplitPane and the NetBeans editor:
+        // setDividerLocation() doesn't work when the split pane has not been
+        // layouted and painted yet. JSplitPane then initially uses a tiny width
+        // for the left editor component, which causes the editor to calculate
+        // invalid offsets and constantly throw exceptions, particularly on
+        // mouse events. Thus, defer adding the two components and setting the
+        // divider's location.
+        splitPane.addComponentListener(new ComponentAdapter() {
+            @Override
+            public void componentResized(ComponentEvent e) {
+                if (firstTimeSplitter && splitPane.getWidth() > 0) {
+                    splitPane.setLeftComponent(leftEditor.getComponent());
+                    splitPane.setRightComponent(rightEditor.getComponent());
+                    splitPane.setDividerLocation(0.5);
+                    firstTimeSplitter = false;
+                }
+            }
+        });
+        cardLayoutPanel.add(splitPane, TWO_GRAPHS);
+        
+        // Text difference => NetBeans diff view
+        // Diff component is created and added on demand
+        textDiffPanel = new JPanel(new BorderLayout());
+        cardLayoutPanel.add(textDiffPanel, TWO_GRAPHS_TEXT_DIFF);
+    }
+
+
+    private StructuredText convert(InputGraph graph, Diagram diagram) {
+        Collection<? extends GraphToTextConverter> converters = Lookup.getDefault().lookupAll(GraphToTextConverter.class);
+        StructuredText text = null;
+        if (converters.size() == 0) {
+            text = new StructuredText(graph.getName());
+            text.println("No graph-to-text converter exists!");
+            return text;
+        }
+
+        for (GraphToTextConverter converter : converters) {
+            if (converter.canConvert(graph)) {
+                text = converter.convert(graph, diagram);
+                if (text == null) {
+                    text = new StructuredText(graph.getName());
+                    text.println("Class " + converter.getClass().getName() + " misbehaved and returned null on graph-to-text conversion!");
+                }
+                return text;
+            }
+        }
+
+        text = new StructuredText(graph.getName());
+        text.println("No appropriate graph-to-text converter found!");
+        return text;
+    }
+
+    private StructuredText createStructuredPlainText(String name, String text) {
+        StructuredText structured = new StructuredText(name);
+        MultiElement multi = new MultiElement();
+        multi.print(text);
+        structured.addChild(multi);
+        return structured;
+    }
+
+    private ItemListener sourceSelectionListener = new ItemListener() {
+        public void itemStateChanged(ItemEvent e) {
+            if (e.getStateChange() == ItemEvent.SELECTED) {
+                if (e.getItem() == GRAPH_TEXT_REPRESENTATION) {
+                    displayDiagram(lastDiagram);
+                } else {
+                    displayGroupProperty(lastDiagram, (String) e.getItem());
+                }
+            }
+        }
+    };
+
+    private void setDiagram(Diagram diagram) {
+        if (diagram == lastDiagram) {
+            // No change => return.
+            return;
+        }
+        lastDiagram = diagram;
+
+        // Rebuild combobox choices
+        Object selection = sourceCombo.getSelectedItem();
+        sourceCombo.removeAllItems();
+        sourceCombo.addItem(GRAPH_TEXT_REPRESENTATION);
+        if (diagram != null) {
+            if (diagram.getGraph().getSourceGraphs() != null) {
+                // Diff graph with source graphs with possibly different groups:
+                // show properties from both graphs
+                Pair<InputGraph, InputGraph> sourceGraphs = diagram.getGraph().getSourceGraphs();
+                Properties props = new Properties(sourceGraphs.getLeft().getGroup().getProperties());
+                if (sourceGraphs.getLeft().getGroup() != sourceGraphs.getRight().getGroup()) {
+                    props.add(sourceGraphs.getRight().getGroup().getProperties());
+                }
+                for (Property p : props) {
+                    sourceCombo.addItem(p.getName());
+                }
+            } else {
+                // Single graph
+                for (Property p : diagram.getGraph().getGroup().getProperties()) {
+                    sourceCombo.addItem(p.getName());
+                }
+            }
+        }
+        // NOTE: The following triggers a display update.
+        sourceCombo.setSelectedItem(selection);
+        if (sourceCombo.getSelectedItem() == null) {
+            // previously selected property doesn't exist in new graph's group:
+            // default to show graph representation
+            sourceCombo.setSelectedItem(GRAPH_TEXT_REPRESENTATION);
+        }
+    }
+
+    private void displayGroupProperty(Diagram diagram, String property) {
+        if (diagram == null) {
+            showCard(NO_GRAPH);
+        } else if (diagram.getGraph().getSourceGraphs() != null) {
+            showCard(TWO_GRAPHS_TEXT_DIFF);
+            textDiffPanel.removeAll();
+            try {
+                Pair<InputGraph, InputGraph> sourceGraphs = diagram.getGraph().getSourceGraphs();
+
+                String ltext = sourceGraphs.getLeft().getGroup().getProperties().get(property);
+                if (ltext == null) {
+                    ltext = "";
+                }
+                StreamSource leftsrc = StreamSource.createSource("left", sourceGraphs.getLeft().getName(), "text/plain", new StringReader(ltext));
+
+                String rtext = sourceGraphs.getRight().getGroup().getProperties().get(property);
+                if (rtext == null) {
+                    rtext = "";
+                }
+                StreamSource rightsrc = StreamSource.createSource("right", sourceGraphs.getRight().getName(), "text/plain", new StringReader(rtext));
+
+                DiffView view = Diff.getDefault().createDiff(leftsrc, rightsrc);
+                textDiffPanel.add(view.getComponent(), BorderLayout.CENTER);
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+            textDiffPanel.revalidate(); // required when card was visible before
+        } else {
+            showCard(ONE_GRAPH);
+            String text = diagram.getGraph().getGroup().getProperties().get(property);
+            singleEditor.setStructuredText(createStructuredPlainText(diagram.getGraph().getName(), text));
+        }
+    }
+
+    private void displayDiagram(Diagram diagram) {
+        if (diagram == null) {
+            showCard(NO_GRAPH);
+        } else if (diagram.getGraph().getSourceGraphs() != null) {
+            showCard(TWO_GRAPHS);
+            Pair<InputGraph, InputGraph> graphs = diagram.getGraph().getSourceGraphs();
+            leftEditor.setStructuredText(convert(graphs.getLeft(), diagram));
+            rightEditor.setStructuredText(convert(graphs.getRight(), diagram));
+
+            // TODO: Hack to update view - remove
+            SelectionCoordinator.getInstance().getHighlightedChangedEvent().fire();
+        } else {
+            showCard(ONE_GRAPH);
+            StructuredText text = convert(diagram.getGraph(), diagram);
+            singleEditor.setStructuredText(text);
+
+            // TODO: Hack to update view - remove
+            SelectionCoordinator.getInstance().getHighlightedChangedEvent().fire();
+        }
+    }
+
+    private ChangedListener<DiagramProvider> diagramChangedListener = new ChangedListener<DiagramProvider>() {
+
+        public void changed(DiagramProvider source) {
+            setDiagram(source.getDiagram());
+        }
+        
+    };
+
+    private void setDiagramProvider(DiagramProvider provider) {
+        if (provider == currentDiagramProvider) {
+            return;
+        }
+
+        if (currentDiagramProvider != null) {
+            currentDiagramProvider.getChangedEvent().removeListener(diagramChangedListener);
+        }
+
+        currentDiagramProvider = provider;
+
+        if (currentDiagramProvider != null) {
+            currentDiagramProvider.getChangedEvent().addListener(diagramChangedListener);
+            setDiagram(currentDiagramProvider.getDiagram());
+        } else {
+            setDiagram(null);
+        }
+    }
+
+    private void showCard(final String card) {
+        cardLayout.show(cardLayoutPanel, card);
+    }
+
+    public void resultChanged(LookupEvent lookupEvent) {
+        DiagramProvider p = Utilities.actionsGlobalContext().lookup(DiagramProvider.class);
+
+        if (p == null) {
+            p = LookupHistory.getLast(DiagramProvider.class);
+        }
+
+        setDiagramProvider(p);
+    }
+
+    /** This method is called from within the constructor to
+     * initialize the form.
+     * WARNING: Do NOT modify this code. The content of this method is
+     * always regenerated by the Form Editor.
+     */
+    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+    private void initComponents() {
+
+        setLayout(new java.awt.BorderLayout());
+    }// </editor-fold>//GEN-END:initComponents
+
+
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    // End of variables declaration//GEN-END:variables
+    /**
+     * Gets default instance. Do not use directly: reserved for *.settings files only,
+     * i.e. deserialization routines; otherwise you could get a non-deserialized instance.
+     * To obtain the singleton instance, use {@link findInstance}.
+     */
+    public static synchronized TextTopComponent getDefault() {
+        if (instance == null) {
+            instance = new TextTopComponent();
+        }
+        return instance;
+    }
+
+    /**
+     * Obtain the TextTopComponent instance. Never call {@link #getDefault} directly!
+     */
+    public static synchronized TextTopComponent findInstance() {
+        TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID);
+        if (win == null) {
+            Logger.getLogger(TextTopComponent.class.getName()).warning(
+                    "Cannot find " + PREFERRED_ID + " component. It will not be located properly in the window system.");
+            return getDefault();
+        }
+        if (win instanceof TextTopComponent) {
+            return (TextTopComponent) win;
+        }
+        Logger.getLogger(TextTopComponent.class.getName()).warning(
+                "There seem to be multiple components with the '" + PREFERRED_ID +
+                "' ID. That is a potential source of errors and unexpected behavior.");
+        return getDefault();
+    }
+
+    @Override
+    public int getPersistenceType() {
+        return TopComponent.PERSISTENCE_ALWAYS;
+    }
+
+    @Override
+    public void componentOpened() {
+
+        DiagramProvider p = LookupHistory.getLast(DiagramProvider.class);
+        setDiagramProvider(p);
+
+        Lookup.Template<DiagramProvider> tpl = new Lookup.Template<DiagramProvider>(DiagramProvider.class);
+        result = Utilities.actionsGlobalContext().lookup(tpl);
+        result.addLookupListener(this);
+    }
+
+    @Override
+    public void componentClosed() {
+        result.removeLookupListener(this);
+        result = null;
+        setDiagramProvider(null);
+    }
+
+    /** replaces this in object stream */
+    @Override
+    public Object writeReplace() {
+        return new ResolvableHelper();
+    }
+
+    @Override
+    protected String preferredID() {
+        return PREFERRED_ID;
+    }
+
+    @Override
+    public void requestActive() {
+        super.requestActive();
+        cardLayoutPanel.requestFocus();
+    }
+
+    final static class ResolvableHelper implements Serializable {
+
+        private static final long serialVersionUID = 1L;
+
+        public Object readResolve() {
+            return TextTopComponent.getDefault();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/GraphTextEditor/src/com/sun/hotspot/igv/graphtexteditor/TextTopComponentSettings.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+To change this template, choose Tools | Templates
+and open the template in the editor.
+-->
+<!DOCTYPE settings PUBLIC "-//NetBeans//DTD Session settings 1.0//EN" "http://www.netbeans.org/dtds/sessionsettings-1_0.dtd">
+<settings version="1.0">
+    <module name="com.sun.hotspot.igv.graphtexteditor" spec="1.0"/>
+    <instanceof class="org.openide.windows.TopComponent"/>
+    <instanceof class="com.sun.hotspot.igv.graphtexteditor.TextTopComponent"/>
+    <instance class="com.sun.hotspot.igv.graphtexteditor.TextTopComponent" method="getDefault"/>
+</settings>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/GraphTextEditor/src/com/sun/hotspot/igv/graphtexteditor/TextTopComponentWstcref.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+To change this template, choose Tools | Templates
+and open the template in the editor.
+-->
+<!DOCTYPE tc-ref PUBLIC "-//NetBeans//DTD Top Component in Mode Properties 2.0//EN" "http://www.netbeans.org/dtds/tc-ref2_0.dtd">
+<tc-ref version="2.0" >
+    <module name="com.sun.hotspot.igv.graphtexteditor" spec="1.0"/>
+    <tc-id id="TextTopComponent"/>
+    <state opened="true"/>
+</tc-ref>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/GraphTextEditor/src/com/sun/hotspot/igv/graphtexteditor/layer.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd">
+<filesystem>
+    <folder name="Actions">
+        <folder name="Window">
+            <file name="com-sun-hotspot-igv-graphtexteditor-TextAction.instance"/>
+        </folder>
+    </folder>
+    <folder name="Menu">
+        <folder name="Window">
+            <file name="TextAction.shadow">
+                <attr name="originalFile" stringvalue="Actions/Window/com-sun-hotspot-igv-graphtexteditor-TextAction.instance"/>
+            </file>
+        </folder>
+    </folder>
+    <folder name="Windows2">
+        <folder name="Components">
+            <file name="TextTopComponent.settings" url="TextTopComponentSettings.xml"/>
+        </folder>
+        <folder name="Modes">
+            <folder name="customRightTopMode">
+                <file name="TextTopComponent.wstcref" url="TextTopComponentWstcref.xml"/>
+            </folder>
+        </folder>
+    </folder>
+    
+</filesystem>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/GraphToText/build.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
+<!-- for some information on what you could do (e.g. targets to override). -->
+<!-- If you delete this file and reopen the project it will be recreated. -->
+<project name="com.sun.hotspot.igv.graphtotext" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project com.sun.hotspot.igv.graphtotext.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/GraphToText/manifest.mf	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+OpenIDE-Module: com.sun.hotspot.igv.graphtotext
+OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/graphtotext/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/GraphToText/nbproject/build-impl.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT  ***
+***         EDIT ../build.xml INSTEAD         ***
+-->
+<project name="com.sun.hotspot.igv.graphtotext-impl" basedir="..">
+    <fail message="Please build using Ant 1.7.1 or higher.">
+        <condition>
+            <not>
+                <antversion atleast="1.7.1"/>
+            </not>
+        </condition>
+    </fail>
+    <property file="nbproject/private/suite-private.properties"/>
+    <property file="nbproject/suite.properties"/>
+    <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
+    <property file="${suite.dir}/nbproject/private/platform-private.properties"/>
+    <property file="${suite.dir}/nbproject/platform.properties"/>
+    <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="name"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{name}" value="${@{value}}"/>
+        </sequential>
+    </macrodef>
+    <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="property"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{property}" value="@{value}"/>
+        </sequential>
+    </macrodef>
+    <property file="${user.properties.file}"/>
+    <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
+        <condition>
+            <not>
+                <contains string="${cluster.path.evaluated}" substring="platform"/>
+            </not>
+        </condition>
+    </fail>
+    <import file="${harness.dir}/build.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/GraphToText/nbproject/genfiles.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,5 @@
+# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
+# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
+nbproject/build-impl.xml.data.CRC32=10eff8f6
+nbproject/build-impl.xml.script.CRC32=b176ca1a
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.45.1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/GraphToText/nbproject/platform.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,175 @@
+cluster.path=\
+    ${nbplatform.active.dir}/ide:\
+    ${nbplatform.active.dir}/platform
+disabled.modules=\
+    org.apache.xml.resolver,\
+    org.mozilla.rhino.patched,\
+    org.netbeans.api.debugger,\
+    org.netbeans.api.java.classpath,\
+    org.netbeans.api.xml,\
+    org.netbeans.core.browser,\
+    org.netbeans.core.execution,\
+    org.netbeans.core.ide,\
+    org.netbeans.core.multiview,\
+    org.netbeans.lib.cvsclient,\
+    org.netbeans.lib.terminalemulator,\
+    org.netbeans.libs.antlr3.runtime,\
+    org.netbeans.libs.bugtracking,\
+    org.netbeans.libs.bugzilla,\
+    org.netbeans.libs.bytelist,\
+    org.netbeans.libs.commons_codec,\
+    org.netbeans.libs.commons_logging,\
+    org.netbeans.libs.commons_net,\
+    org.netbeans.libs.freemarker,\
+    org.netbeans.libs.ini4j,\
+    org.netbeans.libs.jakarta_oro,\
+    org.netbeans.libs.jaxb,\
+    org.netbeans.libs.jsch,\
+    org.netbeans.libs.jsr223,\
+    org.netbeans.libs.jvyamlb,\
+    org.netbeans.libs.jzlib,\
+    org.netbeans.libs.lucene,\
+    org.netbeans.libs.smack,\
+    org.netbeans.libs.svnClientAdapter,\
+    org.netbeans.libs.svnClientAdapter.javahl,\
+    org.netbeans.libs.svnClientAdapter.svnkit,\
+    org.netbeans.libs.swingx,\
+    org.netbeans.libs.xerces,\
+    org.netbeans.modules.autoupdate.services,\
+    org.netbeans.modules.autoupdate.ui,\
+    org.netbeans.modules.bugtracking,\
+    org.netbeans.modules.bugtracking.bridge,\
+    org.netbeans.modules.bugzilla,\
+    org.netbeans.modules.core.kit,\
+    org.netbeans.modules.csl.api,\
+    org.netbeans.modules.css.editor,\
+    org.netbeans.modules.css.visual,\
+    org.netbeans.modules.db,\
+    org.netbeans.modules.db.core,\
+    org.netbeans.modules.db.dataview,\
+    org.netbeans.modules.db.drivers,\
+    org.netbeans.modules.db.kit,\
+    org.netbeans.modules.db.metadata.model,\
+    org.netbeans.modules.db.mysql,\
+    org.netbeans.modules.db.sql.editor,\
+    org.netbeans.modules.db.sql.visualeditor,\
+    org.netbeans.modules.dbapi,\
+    org.netbeans.modules.defaults,\
+    org.netbeans.modules.derby,\
+    org.netbeans.modules.diff,\
+    org.netbeans.modules.dlight.nativeexecution,\
+    org.netbeans.modules.dlight.terminal,\
+    org.netbeans.modules.editor.bookmarks,\
+    org.netbeans.modules.editor.bracesmatching,\
+    org.netbeans.modules.editor.codetemplates,\
+    org.netbeans.modules.editor.completion,\
+    org.netbeans.modules.editor.errorstripe,\
+    org.netbeans.modules.editor.errorstripe.api,\
+    org.netbeans.modules.editor.guards,\
+    org.netbeans.modules.editor.indent.project,\
+    org.netbeans.modules.editor.kit,\
+    org.netbeans.modules.editor.macros,\
+    org.netbeans.modules.editor.plain,\
+    org.netbeans.modules.editor.plain.lib,\
+    org.netbeans.modules.editor.structure,\
+    org.netbeans.modules.extbrowser,\
+    org.netbeans.modules.extexecution,\
+    org.netbeans.modules.extexecution.destroy,\
+    org.netbeans.modules.favorites,\
+    org.netbeans.modules.glassfish.common,\
+    org.netbeans.modules.gototest,\
+    org.netbeans.modules.gsf.codecoverage,\
+    org.netbeans.modules.gsf.testrunner,\
+    org.netbeans.modules.html,\
+    org.netbeans.modules.html.editor,\
+    org.netbeans.modules.html.editor.lib,\
+    org.netbeans.modules.html.lexer,\
+    org.netbeans.modules.html.parser,\
+    org.netbeans.modules.html.validation,\
+    org.netbeans.modules.httpserver,\
+    org.netbeans.modules.hudson,\
+    org.netbeans.modules.hudson.mercurial,\
+    org.netbeans.modules.hudson.subversion,\
+    org.netbeans.modules.ide.kit,\
+    org.netbeans.modules.image,\
+    org.netbeans.modules.javascript.editing,\
+    org.netbeans.modules.javascript.hints,\
+    org.netbeans.modules.javascript.kit,\
+    org.netbeans.modules.javascript.refactoring,\
+    org.netbeans.modules.jellytools.ide,\
+    org.netbeans.modules.jumpto,\
+    org.netbeans.modules.languages,\
+    org.netbeans.modules.languages.diff,\
+    org.netbeans.modules.languages.manifest,\
+    org.netbeans.modules.languages.yaml,\
+    org.netbeans.modules.lexer.nbbridge,\
+    org.netbeans.modules.localhistory,\
+    org.netbeans.modules.mercurial,\
+    org.netbeans.modules.options.editor,\
+    org.netbeans.modules.parsing.api,\
+    org.netbeans.modules.parsing.lucene,\
+    org.netbeans.modules.print.editor,\
+    org.netbeans.modules.project.ant,\
+    org.netbeans.modules.project.libraries,\
+    org.netbeans.modules.projectapi,\
+    org.netbeans.modules.projectui,\
+    org.netbeans.modules.projectui.buildmenu,\
+    org.netbeans.modules.projectuiapi,\
+    org.netbeans.modules.properties,\
+    org.netbeans.modules.properties.syntax,\
+    org.netbeans.modules.refactoring.api,\
+    org.netbeans.modules.schema2beans,\
+    org.netbeans.modules.server,\
+    org.netbeans.modules.servletapi,\
+    org.netbeans.modules.spellchecker,\
+    org.netbeans.modules.spellchecker.apimodule,\
+    org.netbeans.modules.spellchecker.bindings.htmlxml,\
+    org.netbeans.modules.spellchecker.bindings.properties,\
+    org.netbeans.modules.spellchecker.dictionary_en,\
+    org.netbeans.modules.spellchecker.kit,\
+    org.netbeans.modules.subversion,\
+    org.netbeans.modules.swing.validation,\
+    org.netbeans.modules.target.iterator,\
+    org.netbeans.modules.tasklist.kit,\
+    org.netbeans.modules.tasklist.projectint,\
+    org.netbeans.modules.tasklist.todo,\
+    org.netbeans.modules.tasklist.ui,\
+    org.netbeans.modules.terminal,\
+    org.netbeans.modules.usersguide,\
+    org.netbeans.modules.utilities,\
+    org.netbeans.modules.utilities.project,\
+    org.netbeans.modules.versioning,\
+    org.netbeans.modules.versioning.indexingbridge,\
+    org.netbeans.modules.versioning.system.cvss,\
+    org.netbeans.modules.versioning.util,\
+    org.netbeans.modules.web.client.tools.api,\
+    org.netbeans.modules.web.common,\
+    org.netbeans.modules.xml,\
+    org.netbeans.modules.xml.axi,\
+    org.netbeans.modules.xml.catalog,\
+    org.netbeans.modules.xml.core,\
+    org.netbeans.modules.xml.jaxb.api,\
+    org.netbeans.modules.xml.lexer,\
+    org.netbeans.modules.xml.multiview,\
+    org.netbeans.modules.xml.retriever,\
+    org.netbeans.modules.xml.schema.completion,\
+    org.netbeans.modules.xml.schema.model,\
+    org.netbeans.modules.xml.tax,\
+    org.netbeans.modules.xml.text,\
+    org.netbeans.modules.xml.tools,\
+    org.netbeans.modules.xml.wsdl.model,\
+    org.netbeans.modules.xml.xam,\
+    org.netbeans.modules.xml.xdm,\
+    org.netbeans.modules.xsl,\
+    org.netbeans.spi.debugger.ui,\
+    org.netbeans.spi.editor.hints,\
+    org.netbeans.spi.navigator,\
+    org.netbeans.spi.palette,\
+    org.netbeans.spi.tasklist,\
+    org.netbeans.spi.viewmodel,\
+    org.netbeans.swing.dirchooser,\
+    org.openide.compat,\
+    org.openide.execution,\
+    org.openide.options,\
+    org.openide.util.enumerations
+nbplatform.active=default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/GraphToText/nbproject/project.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,2 @@
+javac.source=1.5
+javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/GraphToText/nbproject/project.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.apisupport.project</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
+            <code-name-base>com.sun.hotspot.igv.graphtotext</code-name-base>
+            <suite-component/>
+            <module-dependencies>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.data</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.graph</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.structuredtext</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+            </module-dependencies>
+            <public-packages>
+                <package>com.sun.hotspot.igv.graphtotext</package>
+                <package>com.sun.hotspot.igv.graphtotext.services</package>
+            </public-packages>
+        </data>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/GraphToText/nbproject/suite.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,1 @@
+suite.dir=${basedir}/..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/GraphToText/src/com/sun/hotspot/igv/graphtotext/BFSGraphToTextConverter.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,157 @@
+/*
+ * 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.sun.hotspot.igv.graphtotext;
+
+import com.sun.hotspot.igv.data.InputEdge;
+import com.sun.hotspot.igv.data.InputGraph;
+import com.sun.hotspot.igv.data.InputNode;
+import com.sun.hotspot.igv.data.Pair;
+import com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.graph.Diagram;
+import com.sun.hotspot.igv.graphtotext.services.GraphToTextVisitor;
+import com.sun.hotspot.igv.structuredtext.Element;
+import com.sun.hotspot.igv.structuredtext.StructuredText;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+import java.util.Set;
+
+/**
+ *
+ * @author Thomas
+ */
+public class BFSGraphToTextConverter {
+    
+    private GraphToTextVisitor visitor;
+    private Map<Properties.PropertyMatcher, GraphToTextVisitor> visitorMap;
+    private InputGraph graph;
+    private Diagram diagram;
+    
+    public BFSGraphToTextConverter(GraphToTextVisitor visitor) {
+        this.visitor = visitor;
+        visitorMap = new HashMap<Properties.PropertyMatcher, GraphToTextVisitor>();
+    }
+    
+    public void registerVisitor(GraphToTextVisitor visitor, Properties.PropertyMatcher matcher) {
+        visitorMap.put(matcher, visitor);
+    }
+    
+    private GraphToTextVisitor chooseVisitor(GraphToTextVisitor defaultVisitor, InputNode node) {
+        for(Properties.PropertyMatcher matcher : visitorMap.keySet()) {
+            if(node.getProperties().selectSingle(matcher) != null) {
+                return visitorMap.get(matcher);
+            }
+        }
+        
+        return defaultVisitor;
+    }
+
+    private Element cyclicVisit(GraphToTextVisitor visitor, InputNode node, List<InputEdge> path) {
+        return chooseVisitor(visitor, node).cyclicVisit(node, path);
+    }
+    
+    private Element visit(GraphToTextVisitor visitor, InputNode node, List<InputEdge> path, List<Pair<InputEdge, Element>> children) {
+        return chooseVisitor(visitor, node).visit(node, path, children);
+    }
+    
+    protected Diagram getDiagram() {
+        return diagram;
+    }
+    
+    public StructuredText convert(InputGraph graph, Diagram diagram) {
+        
+        this.graph = graph;
+        this.diagram = diagram;
+        StructuredText text = new StructuredText(graph.getName());
+        
+        Map<InputNode, List<InputEdge>> outgoing = graph.findAllOutgoingEdges();
+        Map<InputNode, List<InputEdge>> pathMap = new HashMap<InputNode, List<InputEdge>>();
+        Queue<InputNode> queue = new LinkedList<InputNode>();
+        List<InputNode> rootNodes = graph.findRootNodes();
+        queue.addAll(rootNodes);
+        for(InputNode node : rootNodes) {
+            pathMap.put(node, new ArrayList<InputEdge>());
+        }
+        
+        Set<InputNode> visited = new HashSet<InputNode>();
+        visited.addAll(rootNodes);
+        
+        Set<InputEdge> fullEdges = new HashSet<InputEdge>();
+        List<InputNode> visitOrder = new ArrayList<InputNode>();
+        while(!queue.isEmpty()) {
+            
+            InputNode current = queue.remove();
+            visitOrder.add(current);
+            List<InputEdge> path = pathMap.get(current);
+            
+            List<InputEdge> edges = outgoing.get(current);
+            for(InputEdge e : edges) {
+                InputNode dest = graph.getNode(e.getTo());
+                if(!visited.contains(dest)) {
+                    queue.add(dest);
+                    visited.add(dest);
+                    List<InputEdge> curPath = new ArrayList<InputEdge>(path);
+                    curPath.add(e);
+                    pathMap.put(dest, curPath);
+                    fullEdges.add(e);
+                }
+            }
+        }
+        
+        
+        
+        Map<InputNode, Element> fullVisitCache = new HashMap<InputNode, Element>();
+        for(int i=visitOrder.size() - 1; i>=0; i--) {
+            InputNode current = visitOrder.get(i);
+            List<InputEdge> path = pathMap.get(current);
+            List<InputEdge> edges = outgoing.get(current);
+            List<Pair<InputEdge, Element>> list = new ArrayList<Pair<InputEdge, Element>>();
+            for(InputEdge e : edges) {
+                if(fullEdges.contains(e)) {
+                    assert fullVisitCache.containsKey(graph.getNode(e.getTo()));
+                    list.add(new Pair<InputEdge, Element>(e, fullVisitCache.get(graph.getNode(e.getTo()))));
+                } else {
+//                    assert fullVisitCache.containsKey(graph.getNode(e.getTo()));
+                    List<InputEdge> curPath = new ArrayList<InputEdge>(path);
+                    curPath.add(e);
+                    list.add(new Pair<InputEdge, Element>(e, cyclicVisit(visitor, graph.getNode(e.getTo()), curPath)));
+                }
+            }
+            
+            Element e = visit(visitor, current, pathMap.get(current), list);
+            fullVisitCache.put(current, e);
+        }
+        
+        for(InputNode node : rootNodes) {
+            text.addChild(fullVisitCache.get(node));
+        }
+        
+        return text;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/GraphToText/src/com/sun/hotspot/igv/graphtotext/Bundle.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,1 @@
+OpenIDE-Module-Name=GraphToText
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/GraphToText/src/com/sun/hotspot/igv/graphtotext/services/AbstractGraphToTextVisitor.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,48 @@
+/*
+ * 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.sun.hotspot.igv.graphtotext.services;
+
+import com.sun.hotspot.igv.data.InputEdge;
+import com.sun.hotspot.igv.data.InputNode;
+import com.sun.hotspot.igv.data.Pair;
+import com.sun.hotspot.igv.structuredtext.Element;
+import com.sun.hotspot.igv.structuredtext.SimpleElement;
+import java.util.List;
+
+/**
+ *
+ * @author Thomas
+ */
+public class AbstractGraphToTextVisitor implements GraphToTextVisitor {
+
+    public Element cyclicVisit(InputNode node, List<InputEdge> path) {
+        return SimpleElement.EMPTY;
+    }
+
+    public Element visit(InputNode node, List<InputEdge> path, List<Pair<InputEdge, Element>> children) {
+        return cyclicVisit(node, path);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/GraphToText/src/com/sun/hotspot/igv/graphtotext/services/GraphToTextConverter.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package com.sun.hotspot.igv.graphtotext.services;
+
+import com.sun.hotspot.igv.data.InputGraph;
+import com.sun.hotspot.igv.graph.Diagram;
+import com.sun.hotspot.igv.structuredtext.StructuredText;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public interface GraphToTextConverter {
+    StructuredText convert(InputGraph graph, Diagram diagram);
+    boolean canConvert(InputGraph graph);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/GraphToText/src/com/sun/hotspot/igv/graphtotext/services/GraphToTextVisitor.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,41 @@
+/*
+ * 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.sun.hotspot.igv.graphtotext.services;
+
+import com.sun.hotspot.igv.data.InputEdge;
+import com.sun.hotspot.igv.data.InputNode;
+import com.sun.hotspot.igv.data.Pair;
+import com.sun.hotspot.igv.structuredtext.Element;
+import java.util.List;
+
+/**
+ *
+ * @author Thomas
+ */
+public interface GraphToTextVisitor {
+
+    Element cyclicVisit(InputNode node, List<InputEdge> path);
+    Element visit(InputNode node, List<InputEdge> path, List<Pair<InputEdge, Element>> children);
+}
--- a/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterNode.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterNode.java	Wed Jul 27 17:32:44 2011 -0700
@@ -93,7 +93,7 @@
         outputSlot = new Port() {
 
             public Point getRelativePosition() {
-                return new Point(size.width / 2, size.height);
+                return new Point(size.width / 2, 0);//size.height);
             }
 
             public Vertex getVertex() {
@@ -183,7 +183,7 @@
 
         for (Link e : subEdges) {
             List<Point> arr = e.getControlPoints();
-            ArrayList<Point> newArr = new ArrayList<Point>();
+            ArrayList<Point> newArr = new ArrayList<Point>(arr.size());
             for (Point p : arr) {
                 if (p != null) {
                     Point p2 = new Point(p);
--- a/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterOutputSlotNode.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterOutputSlotNode.java	Wed Jul 27 17:32:44 2011 -0700
@@ -88,7 +88,7 @@
             public Point getRelativePosition() {
                 Point p = new Point(thisNode.getPosition());
                 p.x += ClusterNode.BORDER;
-                p.y = thisBlockNode.getSize().height;
+                p.y = 0;//thisBlockNode.getSize().height;
                 return p;
             }
 
--- a/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/HierarchicalClusterLayoutManager.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/HierarchicalClusterLayoutManager.java	Wed Jul 27 17:32:44 2011 -0700
@@ -116,7 +116,7 @@
 
         for (Vertex v : graph.getVertices()) {
             Cluster c = v.getCluster();
-            assert c != null;
+            assert c != null : "Cluster of vertex " + v + " is null!";
             clusterNodes.get(c).addSubNode(v);
         }
 
--- a/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/HierarchicalLayoutManager.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/HierarchicalLayoutManager.java	Wed Jul 27 17:32:44 2011 -0700
@@ -101,11 +101,13 @@
         public int yOffset;
         public int bottomYOffset;
         public Vertex vertex; // Only used for non-dummy nodes, otherwise null
+
         public List<LayoutEdge> preds = new ArrayList<LayoutEdge>();
         public List<LayoutEdge> succs = new ArrayList<LayoutEdge>();
         public HashMap<Integer, Integer> outOffsets = new HashMap<Integer, Integer>();
         public HashMap<Integer, Integer> inOffsets = new HashMap<Integer, Integer>();
         public int pos = -1; // Position within layer
+
         public int crossingNumber;
 
         @Override
@@ -276,10 +278,10 @@
                     if (e.link != null) {
                         ArrayList<Point> points = new ArrayList<Point>();
 
-                        Point p = new Point(e.to.x + e.relativeTo, e.to.y + e.to.yOffset);
+                        Point p = new Point(e.to.x + e.relativeTo, e.to.y + e.to.yOffset + e.link.getTo().getRelativePosition().y);
                         points.add(p);
                         if (e.to.inOffsets.containsKey(e.relativeTo)) {
-                            points.add(new Point(p.x, p.y + e.to.inOffsets.get(e.relativeTo)));
+                            points.add(new Point(p.x, p.y + e.to.inOffsets.get(e.relativeTo) + e.link.getTo().getRelativePosition().y));
                         }
 
                         LayoutNode cur = e.from;
@@ -299,9 +301,9 @@
                             cur = curEdge.from;
                         }
 
-                        p = new Point(cur.x + curEdge.relativeFrom, cur.y + cur.height - cur.bottomYOffset);
+                        p = new Point(cur.x + curEdge.relativeFrom, cur.y + cur.height - cur.bottomYOffset + (curEdge.link == null ? 0 : curEdge.link.getFrom().getRelativePosition().y));
                         if (curEdge.from.outOffsets.containsKey(curEdge.relativeFrom)) {
-                            points.add(new Point(p.x, p.y + curEdge.from.outOffsets.get(curEdge.relativeFrom)));
+                            points.add(new Point(p.x, p.y + curEdge.from.outOffsets.get(curEdge.relativeFrom) + (curEdge.link == null ? 0 : curEdge.link.getFrom().getRelativePosition().y)));
                         }
                         points.add(p);
 
@@ -360,10 +362,10 @@
                 for (LayoutEdge e : n.succs) {
                     if (e.link != null) {
                         ArrayList<Point> points = new ArrayList<Point>();
-                        Point p = new Point(e.from.x + e.relativeFrom, e.from.y + e.from.height - e.from.bottomYOffset);
+                        Point p = new Point(e.from.x + e.relativeFrom, e.from.y + e.from.height - e.from.bottomYOffset + e.link.getFrom().getRelativePosition().y);
                         points.add(p);
                         if (e.from.outOffsets.containsKey(e.relativeFrom)) {
-                            points.add(new Point(p.x, p.y + e.from.outOffsets.get(e.relativeFrom)));
+                            points.add(new Point(p.x, p.y + e.from.outOffsets.get(e.relativeFrom) + e.link.getFrom().getRelativePosition().y));
                         }
 
                         LayoutNode cur = e.to;
@@ -387,10 +389,10 @@
                         }
 
 
-                        p = new Point(cur.x + curEdge.relativeTo, cur.y + cur.yOffset);
+                        p = new Point(cur.x + curEdge.relativeTo, cur.y + cur.yOffset + ((curEdge.link == null) ? 0 : curEdge.link.getTo().getRelativePosition().y));
                         points.add(p);
                         if (curEdge.to.inOffsets.containsKey(curEdge.relativeTo)) {
-                            points.add(new Point(p.x, p.y + curEdge.to.inOffsets.get(curEdge.relativeTo)));
+                            points.add(new Point(p.x, p.y + curEdge.to.inOffsets.get(curEdge.relativeTo) + ((curEdge.link == null) ? 0 : curEdge.link.getTo().getRelativePosition().y)));
                         }
 
 
@@ -528,9 +530,11 @@
         }
     };
     private static final Comparator<LayoutNode> nodeProcessingDownComparator = new Comparator<LayoutNode>() {
-
         public int compare(LayoutNode n1, LayoutNode n2) {
             if (n1.vertex == null) {
+                if (n2.vertex == null) {
+                    return 0;
+                }
                 return -1;
             }
             if (n2.vertex == null) {
@@ -543,6 +547,9 @@
 
         public int compare(LayoutNode n1, LayoutNode n2) {
             if (n1.vertex == null) {
+                if (n2.vertex == null) {
+                    return 0;
+                }
                 return -1;
             }
             if (n2.vertex == null) {
@@ -563,12 +570,16 @@
                 n.x = space[n.layer].get(n.pos);
             }
         }
-
-        protected void run() {
-
+        
+        @SuppressWarnings("unchecked")
+        private void createArrays() {
             space = new ArrayList[layers.length];
             downProcessingOrder = new ArrayList[layers.length];
             upProcessingOrder = new ArrayList[layers.length];
+        }
+
+        protected void run() {
+            createArrays();
 
             for (int i = 0; i < layers.length; i++) {
                 space[i] = new ArrayList<Integer>();
@@ -643,6 +654,7 @@
                     result += cur;
                 }
                 return result / size; //median(values);
+
             }
         }
 
@@ -1103,15 +1115,18 @@
                 assert n.layer < layerCount;
             }
         }
-
-        protected void run() {
-
+        
+        @SuppressWarnings("unchecked")
+        private void createLayers() {
             layers = new List[layerCount];
 
             for (int i = 0; i < layerCount; i++) {
                 layers[i] = new ArrayList<LayoutNode>();
             }
+        }
 
+        protected void run() {
+            createLayers();
 
             // Generate initial ordering
             HashSet<LayoutNode> visited = new HashSet<LayoutNode>();
@@ -1146,10 +1161,6 @@
                 downSweep();
                 upSweep();
             }
-
-        /*for(int i=0; i<CROSSING_ITERATIONS; i++) {
-        doubleSweep();
-        }*/
         }
 
         private void initX() {
@@ -1251,44 +1262,6 @@
                 }
             }
         }
-        /*
-        private void doubleSweep() {
-        // Downsweep
-        for(int i=0; i<layerCount*2; i++) {
-        int index = i;
-        if(index >= layerCount) {
-        index = 2*layerCount - i - 1;
-        }
-        for(LayoutNode n : layers[index]) {
-        float sum = 0.0f;
-        for(LayoutEdge e : n.preds) {
-        float cur = e.from.pos;
-        if(e.from.width != 0 && e.relativeFrom != 0) {
-        cur += (float)e.relativeFrom / (float)(e.from.width);
-        }
-        sum += cur;
-        }
-        for(LayoutEdge e : n.succs) {
-        float cur = e.to.pos;
-        if(e.to.width != 0 && e.relativeTo != 0) {
-        cur += (float)e.relativeTo / (float)(e.to.width);
-        }
-        sum += cur;
-        }
-        if(n.preds.size() + n.succs.size() > 0) {
-        sum /= n.preds.size() + n.succs.size();
-        n.crossingNumber = sum;
-        }
-        }
-        Collections.sort(layers[index], crossingNodeComparator);
-        updateXOfLayer(index);
-        int z = 0;
-        for(LayoutNode n : layers[index]) {
-        n.pos = z;
-        z++;
-        }
-        }
-        }*/
 
         private void upSweep() {
             // Upsweep
@@ -1303,7 +1276,7 @@
                     int sum = 0;
                     for (LayoutEdge e : n.succs) {
                         int cur = e.to.x + e.relativeTo;//pos;
-                                                /*
+						/*
                         if(e.to.width != 0 && e.relativeTo != 0) {
                         cur += (float)e.relativeTo / (float)(e.to.width);
                         }*/
@@ -1331,11 +1304,6 @@
             }
         }
 
-        private int evaluate() {
-            // TODO: Implement efficient evaluate / crossing min
-            return 0;
-        }
-
         @Override
         public void postCheck() {
 
@@ -1355,7 +1323,7 @@
 
         protected void run() {
             int curY = 0;
-            //maxLayerHeight = new int[layers.length];
+
             for (int i = 0; i < layers.length; i++) {
                 int maxHeight = 0;
                 int baseLine = 0;
@@ -1383,8 +1351,6 @@
                     }
                 }
 
-                //maxLayerHeight[i] = maxHeight + baseLine + bottomBaseLine;
-
                 curY += maxHeight + baseLine + bottomBaseLine;
                 curY += layerOffset + (int) Math.sqrt(maxXOffset);
             }
@@ -1649,10 +1615,14 @@
         }
 
         protected void run() {
+
+            List<LayoutNode> insertOrder = new ArrayList<LayoutNode>();
+
             HashSet<LayoutNode> set = new HashSet<LayoutNode>();
             for (LayoutNode n : nodes) {
                 if (n.preds.size() == 0) {
                     set.add(n);
+                    insertOrder.add(n);
                     n.layer = 0;
                 }
             }
@@ -1691,6 +1661,7 @@
 
                 for (LayoutNode n : newSet) {
                     n.layer = z;
+                    insertOrder.add(n);
                 }
 
                 // Swap sets
@@ -1700,7 +1671,7 @@
                 z += minLayerDifference;
             }
 
-            optimize(set);
+            optimize(insertOrder);
 
             layerCount = z - minLayerDifference;
 
@@ -1714,23 +1685,22 @@
             for (Vertex v : firstLayerHint) {
                 LayoutNode n = vertexToLayoutNode.get(v);
                 assert n.preds.size() == 0;
+                n.layer = 0;
                 assert n.layer == 0;
             }
         }
 
-        public void optimize(HashSet<LayoutNode> set) {
-
-            for (LayoutNode n : set) {
-                if (n.preds.size() == 0 && n.succs.size() > 0) {
-                    int minLayer = n.succs.get(0).to.layer;
-                    for (LayoutEdge e : n.succs) {
+        public void optimize(List<LayoutNode> insertOrder) {
+            for (int i = insertOrder.size() - 1; i >= 0; i--) {
+                LayoutNode cur = insertOrder.get(i);
+                if (cur.succs.size() > cur.preds.size()) {
+                    int minLayer = cur.succs.get(0).to.layer;
+                    for (LayoutEdge e : cur.succs) {
                         minLayer = Math.min(minLayer, e.to.layer);
                     }
-
-                    n.layer = minLayer - 1;
+                    cur.layer = minLayer - 1;
                 }
             }
-
         }
 
         @Override
@@ -1752,7 +1722,7 @@
 
         protected void run() {
 
-            // Remove self-edges, TODO: Special treatment
+            // Remove self-edges
             for (LayoutNode node : nodes) {
                 ArrayList<LayoutEdge> succs = new ArrayList<LayoutEdge>(node.succs);
                 for (LayoutEdge e : succs) {
@@ -2105,6 +2075,6 @@
     }
 
     public void doRouting(LayoutGraph graph) {
-    // Do nothing for now
+        // Do nothing for now
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/OldHierarchicalLayoutManager.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/OldHierarchicalLayoutManager.java	Wed Jul 27 17:32:44 2011 -0700
@@ -499,7 +499,8 @@
         //}
 
 
-        ArrayList<Node<NodeData, EdgeData>> layers[] = new ArrayList[maxLayer + 1];
+        @SuppressWarnings("unchecked")
+        ArrayList<Node<NodeData, EdgeData>> layers[] = (ArrayList<Node<NodeData, EdgeData>>[]) new ArrayList[maxLayer + 1];
         int layerSizes[] = new int[maxLayer + 1];
         for (int i = 0; i < maxLayer + 1; i++) {
             layers[i] = new ArrayList<Node<NodeData, EdgeData>>();
@@ -754,7 +755,6 @@
 
     private void assignCoordinates(ArrayList<Node<NodeData, EdgeData>> layers[]) {
 
-        // TODO: change this
         for (int i = 0; i < layers.length; i++) {
             ArrayList<Node<NodeData, EdgeData>> curArray = layers[i];
             int curY = 0;
@@ -1114,7 +1114,7 @@
         int removedCount = 0;
         int reversedCount = 0;
 
-        Graph.DFSTraversalVisitor visitor = graph.new DFSTraversalVisitor() {
+        Graph<NodeData, EdgeData>.DFSTraversalVisitor visitor = graph.new DFSTraversalVisitor() {
 
             @Override
             public boolean visitEdge(Edge<NodeData, EdgeData> e, boolean backEdge) {
@@ -1160,7 +1160,7 @@
             n.getData().setLayer(-1);
         }
 
-        Graph.BFSTraversalVisitor traverser = graph.new BFSTraversalVisitor() {
+        Graph<NodeData, EdgeData>.BFSTraversalVisitor traverser = graph.new BFSTraversalVisitor() {
 
             @Override
             public void visitNode(Node<NodeData, EdgeData> n, int depth) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Java6ScriptingProxy/build.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
+<!-- for some information on what you could do (e.g. targets to override). -->
+<!-- If you delete this file and reopen the project it will be recreated. -->
+<project name="com.sun.hotspot.igv.java6scriptingproxy" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project com.sun.hotspot.igv.java6scriptingproxy.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Java6ScriptingProxy/manifest.mf	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+OpenIDE-Module: com.sun.hotspot.igv.java6scriptingproxy
+OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/java6scriptingproxy/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Java6ScriptingProxy/nbproject/build-impl.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT  ***
+***         EDIT ../build.xml INSTEAD         ***
+-->
+<project name="com.sun.hotspot.igv.java6scriptingproxy-impl" basedir="..">
+    <fail message="Please build using Ant 1.7.1 or higher.">
+        <condition>
+            <not>
+                <antversion atleast="1.7.1"/>
+            </not>
+        </condition>
+    </fail>
+    <property file="nbproject/private/suite-private.properties"/>
+    <property file="nbproject/suite.properties"/>
+    <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
+    <property file="${suite.dir}/nbproject/private/platform-private.properties"/>
+    <property file="${suite.dir}/nbproject/platform.properties"/>
+    <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="name"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{name}" value="${@{value}}"/>
+        </sequential>
+    </macrodef>
+    <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="property"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{property}" value="@{value}"/>
+        </sequential>
+    </macrodef>
+    <property file="${user.properties.file}"/>
+    <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
+        <condition>
+            <not>
+                <contains string="${cluster.path.evaluated}" substring="platform"/>
+            </not>
+        </condition>
+    </fail>
+    <import file="${harness.dir}/build.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Java6ScriptingProxy/nbproject/genfiles.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,5 @@
+# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
+# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
+nbproject/build-impl.xml.data.CRC32=485d21b4
+nbproject/build-impl.xml.script.CRC32=341e7d1e
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.45.1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Java6ScriptingProxy/nbproject/project.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,2 @@
+javac.source=1.5
+javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Java6ScriptingProxy/nbproject/project.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.apisupport.project</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
+            <code-name-base>com.sun.hotspot.igv.java6scriptingproxy</code-name-base>
+            <suite-component/>
+            <module-dependencies>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.filter</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.graph</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+            </module-dependencies>
+            <public-packages>
+                <package>com.sun.hotspot.igv.java6scriptingproxy</package>
+            </public-packages>
+        </data>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Java6ScriptingProxy/nbproject/suite.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,1 @@
+suite.dir=${basedir}/..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Java6ScriptingProxy/src/META-INF/services/com.sun.hotspot.igv.filter.ScriptEngineAbstraction	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,1 @@
+com.sun.hotspot.igv.java6scriptingproxy.JavaSE6ScriptEngine
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Java6ScriptingProxy/src/com/sun/hotspot/igv/java6scriptingproxy/Bundle.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,1 @@
+OpenIDE-Module-Name=Java6ScriptingProxy
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Java6ScriptingProxy/src/com/sun/hotspot/igv/java6scriptingproxy/JavaSE6ScriptEngine.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.sun.hotspot.igv.java6scriptingproxy;
+
+import com.sun.hotspot.igv.filter.*;
+import com.sun.hotspot.igv.graph.Diagram;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class JavaSE6ScriptEngine implements ScriptEngineAbstraction {
+
+    private Object engine;
+    private Object bindings;
+    private Method Bindings_put;
+    private Method ScriptEngine_eval;
+
+    public boolean initialize(String jsHelperText) {
+        try {
+            ClassLoader cl = JavaSE6ScriptEngine.class.getClassLoader();
+            Class<?> managerClass = cl.loadClass("javax.script.ScriptEngineManager");
+            Class<?> engineClass = cl.loadClass("javax.script.ScriptEngine");
+            Class<?> bindingsClass = cl.loadClass("javax.script.Bindings");
+            Class<?> contextClass = cl.loadClass("javax.script.ScriptContext");
+
+            Object manager = managerClass.newInstance();
+            Method getEngineByName = managerClass.getMethod("getEngineByName", String.class);
+            engine = getEngineByName.invoke(manager, "ECMAScript");
+            Method eval = engineClass.getMethod("eval", String.class);
+            ScriptEngine_eval = engineClass.getMethod("eval", String.class, bindingsClass);
+            eval.invoke(engine, jsHelperText);
+            Method getContext = engineClass.getMethod("getContext");
+            Object context = getContext.invoke(engine);
+            Method getBindings = contextClass.getMethod("getBindings", Integer.TYPE);
+            Field f = contextClass.getField("ENGINE_SCOPE");
+            bindings = getBindings.invoke(context, f.getInt(null));
+            Bindings_put = bindingsClass.getMethod("put", String.class, Object.class);
+            Bindings_put.invoke(bindings, "IO", System.out);
+
+            /*
+             * Non-reflective code: 
+            ScriptEngineManager sem = new ScriptEngineManager();
+            ScriptEngine e = sem.getEngineByName("ECMAScript");
+            engine = e;
+            e.eval(jsHelperText);
+            Bindings b = e.getContext().getBindings(ScriptContext.ENGINE_SCOPE);
+            b.put("IO", System.out);
+            bindings = b;
+             */
+            
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    public void execute(Diagram d, String code) {
+        try {
+            Bindings_put.invoke(bindings, "graph", d);
+            ScriptEngine_eval.invoke(engine, code, bindings);
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+    }
+}
--- a/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/Cluster.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/Cluster.java	Wed Jul 27 17:32:44 2011 -0700
@@ -37,6 +37,4 @@
     public void setBounds(Rectangle r);
 
     public Set<? extends Cluster> getSuccessors();
-
-    public Set<? extends Cluster> getPredecessors();
 }
--- a/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/LayoutGraph.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/LayoutGraph.java	Wed Jul 27 17:32:44 2011 -0700
@@ -50,9 +50,9 @@
         assert verify();
 
         vertices = new TreeSet<Vertex>();
-        portLinks = new HashMap<Port, Set<Link>>();
-        inputPorts = new HashMap<Vertex, Set<Port>>();
-        outputPorts = new HashMap<Vertex, Set<Port>>();
+        portLinks = new HashMap<Port, Set<Link>>(links.size());
+        inputPorts = new HashMap<Vertex, Set<Port>>(links.size());
+        outputPorts = new HashMap<Vertex, Set<Port>>(links.size());
 
         for (Link l : links) {
             Port p = l.getFrom();
@@ -148,7 +148,7 @@
 
     // Returns a set of vertices with the following properties:
     // - All Vertices in the set startingRoots are elements of the set.
-    // - When starting a DFS at every vertex in the set, every vertex of the
+    // - When starting a DFS at every vertex in the set, every vertex of the 
     //   whole graph is visited.
     public Set<Vertex> findRootVertices(Set<Vertex> startingRoots) {
 
--- a/src/share/tools/IdealGraphVisualizer/NetworkConnection/nbproject/build-impl.xml	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/NetworkConnection/nbproject/build-impl.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -4,6 +4,13 @@
 ***         EDIT ../build.xml INSTEAD         ***
 -->
 <project name="com.sun.hotspot.igv.connection-impl" basedir="..">
+    <fail message="Please build using Ant 1.7.1 or higher.">
+        <condition>
+            <not>
+                <antversion atleast="1.7.1"/>
+            </not>
+        </condition>
+    </fail>
     <property file="nbproject/private/suite-private.properties"/>
     <property file="nbproject/suite.properties"/>
     <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
@@ -16,13 +23,21 @@
             <property name="@{name}" value="${@{value}}"/>
         </sequential>
     </macrodef>
+    <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="property"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{property}" value="@{value}"/>
+        </sequential>
+    </macrodef>
     <property file="${user.properties.file}"/>
     <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
-    <nbmproject2:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
-    <fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'">
+    <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
         <condition>
             <not>
-                <available file="${harness.dir}" type="dir"/>
+                <contains string="${cluster.path.evaluated}" substring="platform"/>
             </not>
         </condition>
     </fail>
--- a/src/share/tools/IdealGraphVisualizer/NetworkConnection/nbproject/genfiles.properties	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/NetworkConnection/nbproject/genfiles.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -1,8 +1,5 @@
-build.xml.data.CRC32=f8e21cb6
-build.xml.script.CRC32=a265137e
-build.xml.stylesheet.CRC32=79c3b980
 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
 # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
-nbproject/build-impl.xml.data.CRC32=f8e21cb6
-nbproject/build-impl.xml.script.CRC32=36f3138c
-nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
+nbproject/build-impl.xml.data.CRC32=5a0e591e
+nbproject/build-impl.xml.script.CRC32=61516e53
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.45.1
--- a/src/share/tools/IdealGraphVisualizer/NetworkConnection/nbproject/project.xml	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/NetworkConnection/nbproject/project.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -27,7 +27,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.11.1.1</specification-version>
+                        <specification-version>7.30.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -35,7 +35,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.5.1</specification-version>
+                        <specification-version>7.18.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -43,7 +43,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.10.1.1</specification-version>
+                        <specification-version>8.14.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.lookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.6.1</specification-version>
                     </run-dependency>
                 </dependency>
             </module-dependencies>
--- a/src/share/tools/IdealGraphVisualizer/README	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/README	Wed Jul 27 17:32:44 2011 -0700
@@ -5,16 +5,11 @@
 was the primary target of the tool.  The tool itself is fairly general
 with only a few modules that contain C2 specific elements.
 
-The tool is built on top of the NetBeans 6.1 rich client
+The tool is built on top of the NetBeans 7 rich client
 infrastructure and so requires NetBeans to build.  It currently
 requires Java 6 to run as it needs support for JavaScript for its
 filtering mechanism and assumes it's built into the platform.  It
-should build out of the box with NetBeans 6.1 and Java 6 or later.
-It's possible to run it on 1.5 by including Rhino on the classpath
-though that currently isn't working correctly.  Support for exporting
-graphs as SVG can be enabled by adding batik to the classpath which
-isn't included by default.  It can be built on top of NetBeans 6.0 if
-you change the required modules to be platform7 instead of platform8.
+should build out of the box with NetBeans 7.0 and Java 6 or later.
 
 The JVM support is controlled by the flag -XX:PrintIdealGraphLevel=#
 where # is:
--- a/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/nbproject/build-impl.xml	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/nbproject/build-impl.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -4,6 +4,13 @@
 ***         EDIT ../build.xml INSTEAD         ***
 -->
 <project name="com.sun.hotspot.igv.rhino-impl" basedir="..">
+    <fail message="Please build using Ant 1.7.1 or higher.">
+        <condition>
+            <not>
+                <antversion atleast="1.7.1"/>
+            </not>
+        </condition>
+    </fail>
     <property file="nbproject/private/suite-private.properties"/>
     <property file="nbproject/suite.properties"/>
     <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
@@ -16,13 +23,21 @@
             <property name="@{name}" value="${@{value}}"/>
         </sequential>
     </macrodef>
+    <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="property"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{property}" value="@{value}"/>
+        </sequential>
+    </macrodef>
     <property file="${user.properties.file}"/>
     <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
-    <nbmproject2:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
-    <fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'">
+    <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
         <condition>
             <not>
-                <available file="${harness.dir}" type="dir"/>
+                <contains string="${cluster.path.evaluated}" substring="platform"/>
             </not>
         </condition>
     </fail>
--- a/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/nbproject/genfiles.properties	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/nbproject/genfiles.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -1,8 +1,5 @@
-build.xml.data.CRC32=0c3e7912
-build.xml.script.CRC32=44d0050c
-build.xml.stylesheet.CRC32=79c3b980
 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
 # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
 nbproject/build-impl.xml.data.CRC32=0c3e7912
-nbproject/build-impl.xml.script.CRC32=7aab3f52
-nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
+nbproject/build-impl.xml.script.CRC32=87376d18
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.45.1
--- a/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/src/com/sun/hotspot/igv/rhino/RhinoScriptEngine.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/src/com/sun/hotspot/igv/rhino/RhinoScriptEngine.java	Wed Jul 27 17:32:44 2011 -0700
@@ -27,7 +27,6 @@
 import com.sun.hotspot.igv.filter.ScriptEngineAbstraction;
 import com.sun.hotspot.igv.graph.Diagram;
 import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 
 /**
@@ -45,21 +44,19 @@
 
     public boolean initialize(String s) {
         this.jsHelperText = s;
-        Class importerTopLevel = null;
+        Class<?> importerTopLevel = null;
         try {
             ClassLoader cl = RhinoScriptEngine.class.getClassLoader();
-            Class context = cl.loadClass("org.mozilla.javascript.Context");
-            Class scriptable = cl.loadClass("org.mozilla.javascript.Scriptable");
+            Class<?> context = cl.loadClass("org.mozilla.javascript.Context");
+            Class<?> scriptable = cl.loadClass("org.mozilla.javascript.Scriptable");
             importerTopLevel = cl.loadClass("org.mozilla.javascript.ImporterTopLevel");
             importer = importerTopLevel.getDeclaredConstructor(context);
-            scope_put = importerTopLevel.getMethod("put", new Class[]{String.class, scriptable, Object.class});
-            cx_evaluateString = context.getDeclaredMethod("evaluateString", new Class[]{scriptable, String.class, String.class, Integer.TYPE, Object.class});
-            context_enter = context.getDeclaredMethod("enter", new Class[0]);
-            context_exit = context.getDeclaredMethod("exit", new Class[0]);
+            scope_put = importerTopLevel.getMethod("put", String.class, scriptable, Object.class);
+            cx_evaluateString = context.getDeclaredMethod("evaluateString", scriptable, String.class, String.class, Integer.TYPE, Object.class);
+            context_enter = context.getDeclaredMethod("enter");
+            context_exit = context.getDeclaredMethod("exit");
             return true;
-        } catch (NoSuchMethodException nsme) {
-            return false;
-        } catch (ClassNotFoundException cnfe) {
+        } catch (Exception e) {
             return false;
         }
     }
@@ -77,9 +74,8 @@
                 // Exit from the context.
                 context_exit.invoke(null, (Object[]) null);
             }
-        } catch (InvocationTargetException iae) {
-        } catch (IllegalAccessException iae) {
-        } catch (InstantiationException iae) {
+        } catch (Exception e) {
+            e.printStackTrace();
         }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/SelectionCoordinator/build.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
+<!-- for some information on what you could do (e.g. targets to override). -->
+<!-- If you delete this file and reopen the project it will be recreated. -->
+<project name="com.sun.hotspot.igv.selectioncoordinator" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project com.sun.hotspot.igv.selectioncoordinator.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/SelectionCoordinator/manifest.mf	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+OpenIDE-Module: com.sun.hotspot.igv.selectioncoordinator
+OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/selectioncoordinator/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/SelectionCoordinator/nbproject/build-impl.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT  ***
+***         EDIT ../build.xml INSTEAD         ***
+-->
+<project name="com.sun.hotspot.igv.selectioncoordinator-impl" basedir="..">
+    <fail message="Please build using Ant 1.7.1 or higher.">
+        <condition>
+            <not>
+                <antversion atleast="1.7.1"/>
+            </not>
+        </condition>
+    </fail>
+    <property file="nbproject/private/suite-private.properties"/>
+    <property file="nbproject/suite.properties"/>
+    <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
+    <property file="${suite.dir}/nbproject/private/platform-private.properties"/>
+    <property file="${suite.dir}/nbproject/platform.properties"/>
+    <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="name"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{name}" value="${@{value}}"/>
+        </sequential>
+    </macrodef>
+    <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="property"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{property}" value="@{value}"/>
+        </sequential>
+    </macrodef>
+    <property file="${user.properties.file}"/>
+    <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
+        <condition>
+            <not>
+                <contains string="${cluster.path.evaluated}" substring="platform"/>
+            </not>
+        </condition>
+    </fail>
+    <import file="${harness.dir}/build.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/SelectionCoordinator/nbproject/genfiles.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,5 @@
+# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
+# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
+nbproject/build-impl.xml.data.CRC32=13553862
+nbproject/build-impl.xml.script.CRC32=3db87c68
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.45.1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/SelectionCoordinator/nbproject/platform.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,129 @@
+# Deprecated since 5.0u1; for compatibility with 5.0:
+disabled.clusters=\
+    apisupport1,\
+    gsf1,\
+    harness,\
+    java2,\
+    nb6.1,\
+    profiler3
+disabled.modules=\
+    org.apache.xml.resolver,\
+    org.netbeans.api.debugger,\
+    org.netbeans.api.xml,\
+    org.netbeans.core.execution,\
+    org.netbeans.core.ide,\
+    org.netbeans.core.multiview,\
+    org.netbeans.core.nativeaccess,\
+    org.netbeans.core.output2,\
+    org.netbeans.insane,\
+    org.netbeans.lib.cvsclient,\
+    org.netbeans.libs.commons_logging,\
+    org.netbeans.libs.freemarker,\
+    org.netbeans.libs.ini4j,\
+    org.netbeans.libs.jna,\
+    org.netbeans.libs.jsch,\
+    org.netbeans.libs.jsr223,\
+    org.netbeans.libs.lucene,\
+    org.netbeans.libs.svnClientAdapter,\
+    org.netbeans.libs.xerces,\
+    org.netbeans.modules.applemenu,\
+    org.netbeans.modules.autoupdate.services,\
+    org.netbeans.modules.autoupdate.ui,\
+    org.netbeans.modules.classfile,\
+    org.netbeans.modules.core.kit,\
+    org.netbeans.modules.db,\
+    org.netbeans.modules.db.core,\
+    org.netbeans.modules.db.drivers,\
+    org.netbeans.modules.db.kit,\
+    org.netbeans.modules.db.mysql,\
+    org.netbeans.modules.db.sql.editor,\
+    org.netbeans.modules.db.sql.visualeditor,\
+    org.netbeans.modules.dbapi,\
+    org.netbeans.modules.defaults,\
+    org.netbeans.modules.diff,\
+    org.netbeans.modules.editor.bookmarks,\
+    org.netbeans.modules.editor.bracesmatching,\
+    org.netbeans.modules.editor.codetemplates,\
+    org.netbeans.modules.editor.completion,\
+    org.netbeans.modules.editor.errorstripe,\
+    org.netbeans.modules.editor.errorstripe.api,\
+    org.netbeans.modules.editor.guards,\
+    org.netbeans.modules.editor.highlights,\
+    org.netbeans.modules.editor.macros,\
+    org.netbeans.modules.editor.plain,\
+    org.netbeans.modules.editor.plain.lib,\
+    org.netbeans.modules.editor.structure,\
+    org.netbeans.modules.extbrowser,\
+    org.netbeans.modules.favorites,\
+    org.netbeans.modules.gototest,\
+    org.netbeans.modules.httpserver,\
+    org.netbeans.modules.ide.kit,\
+    org.netbeans.modules.image,\
+    org.netbeans.modules.javahelp,\
+    org.netbeans.modules.jumpto,\
+    org.netbeans.modules.languages,\
+    org.netbeans.modules.languages.bat,\
+    org.netbeans.modules.languages.diff,\
+    org.netbeans.modules.languages.manifest,\
+    org.netbeans.modules.languages.sh,\
+    org.netbeans.modules.lexer.editorbridge,\
+    org.netbeans.modules.lexer.nbbridge,\
+    org.netbeans.modules.localhistory,\
+    org.netbeans.modules.masterfs,\
+    org.netbeans.modules.mercurial,\
+    org.netbeans.modules.progress.ui,\
+    org.netbeans.modules.project.ant,\
+    org.netbeans.modules.project.libraries,\
+    org.netbeans.modules.projectui,\
+    org.netbeans.modules.projectuiapi,\
+    org.netbeans.modules.properties,\
+    org.netbeans.modules.properties.syntax,\
+    org.netbeans.modules.refactoring.api,\
+    org.netbeans.modules.schema2beans,\
+    org.netbeans.modules.sendopts,\
+    org.netbeans.modules.server,\
+    org.netbeans.modules.servletapi,\
+    org.netbeans.modules.subversion,\
+    org.netbeans.modules.tasklist.kit,\
+    org.netbeans.modules.tasklist.projectint,\
+    org.netbeans.modules.tasklist.todo,\
+    org.netbeans.modules.tasklist.ui,\
+    org.netbeans.modules.templates,\
+    org.netbeans.modules.timers,\
+    org.netbeans.modules.usersguide,\
+    org.netbeans.modules.utilities,\
+    org.netbeans.modules.utilities.project,\
+    org.netbeans.modules.versioning,\
+    org.netbeans.modules.versioning.system.cvss,\
+    org.netbeans.modules.versioning.util,\
+    org.netbeans.modules.web.flyingsaucer,\
+    org.netbeans.modules.xml,\
+    org.netbeans.modules.xml.axi,\
+    org.netbeans.modules.xml.catalog,\
+    org.netbeans.modules.xml.core,\
+    org.netbeans.modules.xml.lexer,\
+    org.netbeans.modules.xml.multiview,\
+    org.netbeans.modules.xml.retriever,\
+    org.netbeans.modules.xml.schema.completion,\
+    org.netbeans.modules.xml.schema.model,\
+    org.netbeans.modules.xml.tax,\
+    org.netbeans.modules.xml.text,\
+    org.netbeans.modules.xml.tools,\
+    org.netbeans.modules.xml.wsdl.model,\
+    org.netbeans.modules.xml.xam,\
+    org.netbeans.modules.xml.xdm,\
+    org.netbeans.modules.xsl,\
+    org.netbeans.spi.debugger.ui,\
+    org.netbeans.spi.editor.hints,\
+    org.netbeans.spi.navigator,\
+    org.netbeans.spi.palette,\
+    org.netbeans.spi.tasklist,\
+    org.netbeans.spi.viewmodel,\
+    org.netbeans.swing.dirchooser,\
+    org.openide.compat,\
+    org.openide.util.enumerations
+enabled.clusters=\
+    ide9,\
+    platform8
+nbjdk.active=default
+nbplatform.active=default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/SelectionCoordinator/nbproject/project.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,2 @@
+javac.source=1.5
+javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/SelectionCoordinator/nbproject/project.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.apisupport.project</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
+            <code-name-base>com.sun.hotspot.igv.selectioncoordinator</code-name-base>
+            <suite-component/>
+            <module-dependencies>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.data</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+            </module-dependencies>
+            <public-packages>
+                <package>com.sun.hotspot.igv.selectioncoordinator</package>
+            </public-packages>
+        </data>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/SelectionCoordinator/nbproject/suite.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,1 @@
+suite.dir=${basedir}/..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/SelectionCoordinator/src/com/sun/hotspot/igv/selectioncoordinator/Bundle.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,1 @@
+OpenIDE-Module-Name=SelectionCoordinator
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/SelectionCoordinator/src/com/sun/hotspot/igv/selectioncoordinator/SelectionCoordinator.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,139 @@
+/*
+ * 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.sun.hotspot.igv.selectioncoordinator;
+
+import com.sun.hotspot.igv.data.ChangedEvent;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ *
+ * @author Thomas
+ */
+public class SelectionCoordinator {
+
+    private static SelectionCoordinator singleInstance = new SelectionCoordinator();
+    private Set<Object> selectedObjects;
+    private Set<Object> highlightedObjects;
+    private ChangedEvent<SelectionCoordinator> selectedChangedEvent;
+    private ChangedEvent<SelectionCoordinator> highlightedChangedEvent;
+
+    public static SelectionCoordinator getInstance() {
+        return singleInstance;
+    }
+
+    private SelectionCoordinator() {
+        selectedChangedEvent = new ChangedEvent<SelectionCoordinator>(this);
+        highlightedChangedEvent = new ChangedEvent<SelectionCoordinator>(this);
+        selectedObjects = new HashSet<Object>();
+        highlightedObjects = new HashSet<Object>();
+    }
+
+    public Set<Object> getSelectedObjects() {
+        return Collections.unmodifiableSet(selectedObjects);
+    }
+
+    public Set<Object> getHighlightedObjects() {
+        return Collections.unmodifiableSet(highlightedObjects);
+    }
+
+    public ChangedEvent<SelectionCoordinator> getHighlightedChangedEvent() {
+        return highlightedChangedEvent;
+    }
+
+    public ChangedEvent<SelectionCoordinator> getSelectedChangedEvent() {
+        return selectedChangedEvent;
+    }
+
+    public void addHighlighted(Object o) {
+        if (!highlightedObjects.contains(o)) {
+            highlightedObjects.add(o);
+            highlightedObjectsChanged();
+        }
+    }
+
+    public void removeHighlighted(Object o) {
+        if (highlightedObjects.contains(o)) {
+            highlightedObjects.remove(o);
+            highlightedObjectsChanged();
+        }
+    }
+
+    public void addAllHighlighted(Set<? extends Object> s) {
+        int oldSize = highlightedObjects.size();
+        highlightedObjects.addAll(s);
+        if (oldSize != highlightedObjects.size()) {
+            highlightedObjectsChanged();
+        }
+    }
+
+    public void removeAllHighlighted(Set<? extends Object> s) {
+        int oldSize = highlightedObjects.size();
+        highlightedObjects.removeAll(s);
+        if (oldSize != highlightedObjects.size()) {
+            highlightedObjectsChanged();
+        }
+    }
+
+    private void highlightedObjectsChanged() {
+        highlightedChangedEvent.fire();
+
+    }
+
+    public void addAllSelected(Set<? extends Object> s) {
+        int oldSize = selectedObjects.size();
+        selectedObjects.addAll(s);
+        if (oldSize != selectedObjects.size()) {
+            selectedObjectsChanged();
+        }
+    }
+
+    public void removeAllSelected(Set<? extends Object> s) {
+        int oldSize = selectedObjects.size();
+        selectedObjects.removeAll(s);
+        if (oldSize != selectedObjects.size()) {
+            selectedObjectsChanged();
+        }
+    }
+
+    public void setSelectedObjects(Set<? extends Object> s) {
+        assert s != null;
+        selectedObjects.clear();
+        selectedObjects.addAll(s);
+        selectedObjectsChanged();
+    }
+
+    private void selectedObjectsChanged() {
+        selectedChangedEvent.fire();
+    }
+
+    public void setHighlightedObjects(Set<? extends Object> s) {
+        assert s != null;
+        this.highlightedObjects.clear();
+        this.highlightedObjects.addAll(s);
+        highlightedObjectsChanged();
+    }
+}
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/nbproject/project.xml	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/ServerCompiler/nbproject/project.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -14,6 +14,30 @@
                         <specification-version>1.0</specification-version>
                     </run-dependency>
                 </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.graph</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.graphtotext</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.structuredtext</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
             </module-dependencies>
             <public-packages/>
         </data>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/META-INF/services/com.sun.hotspot.igv.graphtotext.services.GraphToTextConverter	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,1 @@
+com.sun.hotspot.igv.servercompiler.ServerCompilerGraphToTextConverter
\ No newline at end of file
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/JavaGroupOrganizer.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/JavaGroupOrganizer.java	Wed Jul 27 17:32:44 2011 -0700
@@ -68,7 +68,7 @@
     }
 
     private void buildResult(List<Pair<String, List<Group>>> result, List<Group> groups, NameProvider provider) {
-        HashMap<String, List<Group>> map = new HashMap<String, List<Group>>();
+        HashMap<String, List<Group>> map = new HashMap<String, List<Group>>(groups.size());
         for (Group g : groups) {
             String s = provider.getName(g);
 
@@ -113,7 +113,7 @@
             }
 
             int current = firstPoint;
-            while (current > 0 && name.charAt(current) != ' ') {
+            while (current >= 0 && name.charAt(current) != ' ') {
                 current--;
             }
 
@@ -145,10 +145,10 @@
             }
 
             int current = firstPoint;
-            while (current > 0 && name.charAt(current) != ' ') {
+            while (current >= 0 && name.charAt(current) != ' ') {
                 current--;
             }
-
+            
             String fullClassName = name.substring(current + 1, firstParenthese);
             int lastPoint = fullClassName.lastIndexOf(".");
             if (lastPoint == -1) {
@@ -182,7 +182,7 @@
             }
 
             int current = firstPoint;
-            while (current > 0 && name.charAt(current) != ' ') {
+            while (current >= 0 && name.charAt(current) != ' ') {
                 current--;
             }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/ServerCompilerGraphToTextConverter.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.sun.hotspot.igv.servercompiler;
+
+import com.sun.hotspot.igv.data.InputBlock;
+import com.sun.hotspot.igv.data.InputEdge;
+import com.sun.hotspot.igv.data.InputGraph;
+import com.sun.hotspot.igv.data.InputNode;
+import com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.data.Properties.PropertyMatcher;
+import com.sun.hotspot.igv.data.Properties.PropertySelector;
+import com.sun.hotspot.igv.graph.Diagram;
+import com.sun.hotspot.igv.graph.Figure;
+import com.sun.hotspot.igv.graphtotext.services.GraphToTextConverter;
+import com.sun.hotspot.igv.structuredtext.Element;
+import com.sun.hotspot.igv.structuredtext.MultiElement;
+import com.sun.hotspot.igv.structuredtext.SimpleElement;
+import com.sun.hotspot.igv.structuredtext.StructuredText;
+import java.awt.Color;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.swing.text.Style;
+import javax.swing.text.StyleConstants;
+import javax.swing.text.StyleContext;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class ServerCompilerGraphToTextConverter implements GraphToTextConverter {
+
+
+    private Map<InputNode, Set<Figure>> map;
+    private Map<InputNode, List<InputEdge>> ingoingEdges;
+    private Map<InputNode, List<InputEdge>> outgoingEdges;
+    private InputGraph graph;
+
+    private Collection<InputNode> sortNodes(Collection<InputNode> nodes) {
+        List<InputNode> result = new ArrayList<InputNode>(nodes);
+
+        Collections.sort(result, InputNode.getPropertyComparator("idx"));
+
+
+        return result;
+    }
+
+    public StructuredText convert(InputGraph graph, Diagram diagram) {
+
+        this.graph = graph;
+        map = diagram.calcSourceToFigureRelation();
+        ingoingEdges = graph.findAllIngoingEdges();
+        outgoingEdges = graph.findAllOutgoingEdges();
+
+        final StructuredText result = new StructuredText(graph.getName());
+
+        for (InputBlock b : graph.getBlocks()) {
+            result.addChild(new SimpleElement("Block " + b.getName() + "\n"));
+            for (InputNode n : sortNodes(b.getNodes())) {
+                result.addChild(getNodeElement(n));
+            }
+        }
+
+        boolean first = true;
+        for (InputNode n : sortNodes(graph.getNodes())) {
+            if (graph.getBlock(n) == null) {
+                if (first) {
+                    first = false;
+                    result.addChild(new SimpleElement("No block: \n"));
+                }
+                result.addChild(getNodeElement(n));
+            }
+        }
+
+
+        return result;
+    }
+
+    private Element getNodeNameElement(InputNode n) {
+
+        final SimpleElement name = new SimpleElement(n.getProperties().get("idx") + " " + n.getProperties().get("name"), calcStyle(n));
+        name.addSource(n.getId());
+        return name;
+    }
+
+    private Element getNodeSmallElement(InputNode n) {
+        final SimpleElement id = new SimpleElement(n.getProperties().get("idx"), calcStyle(n));
+        id.addSource(n.getId());
+        return id;
+    }
+
+    private Element getNodeElement(InputNode n) {
+
+        final MultiElement result = new MultiElement();
+
+        result.print("\t");
+        result.addChild(getNodeNameElement(n));
+
+        result.print(" === ");
+        
+        for (InputEdge e : outgoingEdges.get(n)) {
+            result.print(" ");
+            result.addChild(getNodeSmallElement(graph.getNode(e.getTo())));
+            result.print(" ");
+        }
+
+        result.print(" [[");
+
+        for (InputEdge e : ingoingEdges.get(n)) {
+            result.print(" ");
+            result.addChild(getNodeSmallElement(graph.getNode(e.getFrom())));
+            result.print(" ");
+        }
+
+        result.print("]] ");
+        
+        result.print(n.getProperties().get("dump_spec"));
+
+        result.print("\n");
+
+        return result;
+    }
+    
+    private static final PropertyMatcher MATCHER = new Properties.RegexpPropertyMatcher("name", "Root");
+    public boolean canConvert(InputGraph graph) {
+        return new PropertySelector<InputNode>(graph.getNodes()).selectSingle(MATCHER) != null;
+    }
+
+    private Color calcColor(InputNode node) {
+        Set<Figure> figureSet = this.map.get(node);
+        if(figureSet != null && figureSet.size() == 1) {
+            return figureSet.iterator().next().getColor();
+        } else {
+            return Color.WHITE;
+        }
+    }
+
+    private Color lessColor(Color c) {
+        return new Color(255 - (255 - c.getRed()) / 4, 255 - (255 - c.getGreen()) / 4, 255 - (255 - c.getBlue()) / 4);
+    }
+
+    private Style calcStyle(InputNode node) {
+        Color c = calcColor(node);
+        Style defaultStyle = StyleContext.getDefaultStyleContext().getStyle(StyleContext.DEFAULT_STYLE);
+        Style newStyle = StyleContext.getDefaultStyleContext().addStyle(null, defaultStyle);
+
+        StyleConstants.setBackground(newStyle, lessColor(c));
+        return newStyle;
+    }
+}
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/ServerCompilerScheduler.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/ServerCompilerScheduler.java	Wed Jul 27 17:32:44 2011 -0700
@@ -93,7 +93,7 @@
 
             if (!visited.contains(parent)) {
                 visited.add(parent);
-                InputBlock block = new InputBlock(graph, "" + blockCount);
+                InputBlock block = graph.addBlock(Integer.toString(blockCount));
                 blocks.add(block);
                 if (parent == root) {
                     rootBlock = block;
@@ -125,7 +125,7 @@
                                 n = n.preds.get(0);
                             }
                             if (n.block != null) {
-                                n.block.addSuccessor(block);
+                                graph.addBlockEdge(n.block, block);
                             }
                         }
                     }
@@ -136,12 +136,12 @@
                         for (Node n2 : n.succs) {
 
                             if (n2 != parent && n2.block != null && n2.block != rootBlock) {
-                                block.addSuccessor(n2.block);
+                                graph.addBlockEdge(block, n2.block);
                             }
                         }
                     } else {
                         if (n != parent && n.block != null && n.block != rootBlock) {
-                            block.addSuccessor(n.block);
+                            graph.addBlockEdge(block, n.block);
                         }
                     }
                 }
@@ -161,7 +161,7 @@
                 }
 
                 if (pushed == 0 && p == root) {
-                // TODO: special handling when root backedges are not built yet
+                    // TODO: special handling when root backedges are not built yet
                 }
             }
         }
@@ -174,7 +174,7 @@
         }
 
         int z = 0;
-        blockIndex = new HashMap<InputBlock, Integer>();
+        blockIndex = new HashMap<InputBlock, Integer>(blocks.size());
         for (InputBlock b : blocks) {
             blockIndex.put(b, z);
             z++;
@@ -186,19 +186,23 @@
     }
 
     public Collection<InputBlock> schedule(InputGraph graph) {
+        if (graph.getNodes().isEmpty()) {
+            return Collections.emptyList();
+        }
+
         if (graph.getBlocks().size() > 0) {
             Collection<InputNode> tmpNodes = new ArrayList<InputNode>(graph.getNodes());
             for (InputNode n : tmpNodes) {
                 String block = getBlockName(n);
                 if (graph.getBlock(n) == null) {
-                    graph.getBlock(block).addNode(n);
+                    graph.getBlock(block).addNode(n.getId());
                     assert graph.getBlock(n) != null;
                 }
             }
             return graph.getBlocks();
         } else {
             nodes = new ArrayList<Node>();
-            inputNodeToNode = new HashMap<InputNode, Node>();
+            inputNodeToNode = new HashMap<InputNode, Node>(graph.getNodes().size());
 
             this.graph = graph;
             buildUpGraph();
@@ -207,7 +211,16 @@
             buildCommonDominators();
             scheduleLatest();
 
+            InputBlock noBlock = null;
             for (InputNode n : graph.getNodes()) {
+                if (graph.getBlock(n) == null) {
+                    if (noBlock == null) {
+                        noBlock = graph.addBlock("(no block)");
+                        blocks.add(noBlock);
+                    }
+                    
+                    graph.setBlock(n, noBlock);
+                }
                 assert graph.getBlock(n) != null;
             }
 
@@ -215,10 +228,12 @@
         }
     }
 
-    public void scheduleLatest() {
-
-
+    private void scheduleLatest() {
         Node root = findRoot();
+        if(root == null) {
+            assert false : "No root found!";
+            return;
+        }
 
         // Mark all nodes reachable in backward traversal from root
         Set<Node> reachable = new HashSet<Node>();
@@ -374,12 +389,12 @@
     }
 
     public void buildDominators() {
-        dominatorMap = new HashMap<InputBlock, InputBlock>();
+        dominatorMap = new HashMap<InputBlock, InputBlock>(graph.getBlocks().size());
         if (blocks.size() == 0) {
             return;
         }
-        Vector<BlockIntermediate> intermediate = new Vector<BlockIntermediate>();
-        Map<InputBlock, BlockIntermediate> map = new HashMap<InputBlock, BlockIntermediate>();
+        Vector<BlockIntermediate> intermediate = new Vector<BlockIntermediate>(graph.getBlocks().size());
+        Map<InputBlock, BlockIntermediate> map = new HashMap<InputBlock, BlockIntermediate>(graph.getBlocks().size());
         int z = 0;
         for (InputBlock b : blocks) {
             BlockIntermediate bi = new BlockIntermediate();
@@ -538,15 +553,30 @@
     }
 
     private Node findRoot() {
+        Node minNode = null;
+        Node alternativeRoot = null;
 
-        for (Node n : nodes) {
-            InputNode inputNode = n.inputNode;
-            if (inputNode.getProperties().get("name").equals("Root")) {
-                return n;
+        for (Node node : nodes) {
+            InputNode inputNode = node.inputNode;
+            String s = inputNode.getProperties().get("name");
+            if (s != null && s.equals("Root")) {
+                return node;
+            }
+
+            if (alternativeRoot == null && node.preds.isEmpty()) {
+                alternativeRoot = node;
+            }
+
+            if (minNode == null || node.inputNode.getId() < minNode.inputNode.getId()) {
+                minNode = node;
             }
         }
 
-        return null;
+        if (alternativeRoot != null) {
+            return alternativeRoot;
+        } else {
+            return minNode;
+        }
     }
 
     public void buildUpGraph() {
@@ -562,7 +592,7 @@
             inputNodeToNode.put(n, node);
         }
 
-        Map<Integer, List<InputEdge>> edgeMap = new HashMap<Integer, List<InputEdge>>();
+        Map<Integer, List<InputEdge>> edgeMap = new HashMap<Integer, List<InputEdge>>(graph.getEdges().size());
         for (InputEdge e : graph.getEdges()) {
 
             int to = e.getTo();
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/color.filter	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/color.filter	Wed Jul 27 17:32:44 2011 -0700
@@ -1,5 +1,18 @@
 colorize("name", ".*", yellow);
 colorize("name", "Catch.*", blue);
-
 colorize("name", "Region|Loop|CountedLoop|Root", red);
 colorize("name", "CProj|IfFalse|IfTrue|JProj|CatchProj", magenta);
+colorize("name", "Con.*", orange);
+colorize("name", "Parm|Proj", lightGray);
+
+// Nodes with bci
+colorize("bci", "..*", magenta);
+
+// Line style
+var f = new ColorFilter("Line Style filter");
+f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "int:")), null, Color.BLUE, null));
+f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "control")), null, Color.RED, null));
+f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "memory")), null, Color.GREEN, null));
+f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "tuple:")), null, Color.MAGENTA, null));
+f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "bottom")), null, Color.LIGHT_GRAY, null));
+f.apply(graph);
\ No newline at end of file
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/combine.filter	Tue Jun 28 10:57:38 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-var f = new CombineFilter("Combine Filter");
-f.addRule(new CombineFilter.CombineRule(new Properties.RegexpPropertyMatcher("name", ".*"), new Properties.RegexpPropertyMatcher("name", "Proj|IfFalse|IfTrue|JProj|MachProj|JumpProj|CatchProj")));
-f.addRule(new CombineFilter.CombineRule(new Properties.RegexpPropertyMatcher("name", "Cmp.*"), new Properties.RegexpPropertyMatcher("name", "Bool")));
-f.apply(graph);
\ No newline at end of file
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/extendedColor.filter	Tue Jun 28 10:57:38 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-colorize("name", "Con.*", orange);
-colorize("name", "Parm|Proj", lightGray);
-colorize("bci", "..*", magenta);
\ No newline at end of file
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/linestyle.filter	Tue Jun 28 10:57:38 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-var f = new ColorFilter("Line Style filter");
-f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "int:")), null, Color.BLUE, null));
-f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "control")), null, Color.RED, null));
-f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "memory")), null, Color.GREEN, null));
-f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "tuple:")), null, Color.MAGENTA, null));
-f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "bottom")), null, Color.LIGHT_GRAY, null));
-f.apply(graph);
\ No newline at end of file
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/onlyControlFlow.filter	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/onlyControlFlow.filter	Wed Jul 27 17:32:44 2011 -0700
@@ -20,5 +20,5 @@
     ), false
   )
 );
-f.addRule( new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.RegexpPropertyMatcher("name", "Phi|Store.")), false));
+f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.RegexpPropertyMatcher("name", "Phi|Store."))));
 f.apply(graph);
\ No newline at end of file
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/register.filter	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/register.filter	Wed Jul 27 17:32:44 2011 -0700
@@ -1,4 +1,5 @@
+// Register coloring
 colorize("reg", "EAX", green);
 colorize("reg", "EFLAGS", gray);
 colorize("reg", "EBP", orange);
-colorize("reg", "ECX", cyan);
+colorize("reg", "ECX", cyan);
\ No newline at end of file
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/remove.filter	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/remove.filter	Wed Jul 27 17:32:44 2011 -0700
@@ -1,1 +1,8 @@
-remove("dump_spec", "FramePtr|ReturnAdr|I_O"); 
\ No newline at end of file
+remove("dump_spec", "FramePtr|ReturnAdr|I_O"); 
+removeInputs("name", "Root");
+var f = new RemoveSelfLoopsFilter("Remove Self-Loops");
+f.apply(graph);
+removeInputs("name", "SafePoint|CallStaticJava|CallDynamicJava|CallJava|CallLeaf|CallRuntime|AbstractLock|CallLeafNoFP|Call|CallStaticJavaDirect", 5);
+removeInputs("name", "Unlock|Lock", 7);
+removeInputs("name", "Allocate", 7);
+removeInputs("name", "AllocateArray", 9);
\ No newline at end of file
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/removeMemory.filter	Tue Jun 28 10:57:38 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-
-//var f = new RemoveFilter("Remove Memory");
-//f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.StringPropertyMatcher("dump_spec", "Memory")), false));
-//f.addRule(new RemoveFilter.RemoveRule(new AndSelector(new MatcherSelector(new Properties.StringPropertyMatcher("name", "Proj")), new MatcherSelector(new Properties.StringPropertyMatcher("type", "memory"))), false));
-//f.apply(graph);
-
-remove("dump_spec", "Memory");
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/removeRootInputs.filter	Tue Jun 28 10:57:38 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-removeInputs("name", "Root");
\ No newline at end of file
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/removeSafepointInputs.filter	Tue Jun 28 10:57:38 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-removeInputs("name", "SafePoint|CallStaticJava|CallDynamicJava|CallJava|CallLeaf|CallRuntime|AbstractLock|CallLeafNoFP|Call|CallStaticJavaDirect", 5);
-removeInputs("name", "Unlock|Lock", 7);
-removeInputs("name", "Allocate", 7);
-removeInputs("name", "AllocateArray", 9);
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/removeSelfLoops.filter	Tue Jun 28 10:57:38 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-var f = new RemoveSelfLoopsFilter("Remove Self-Loops");
-f.apply(graph);
\ No newline at end of file
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/split.filter	Tue Jun 28 10:57:38 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-split("name", "BoxLock");
-split("name", "(Con.*)|(loadCon.*)");
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/structural.filter	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,6 @@
+var f = new CombineFilter("Combine Filter");
+f.addRule(new CombineFilter.CombineRule(new Properties.RegexpPropertyMatcher("name", ".*"), new Properties.RegexpPropertyMatcher("name", "Proj|IfFalse|IfTrue|JProj|MachProj|JumpProj|CatchProj")));
+f.addRule(new CombineFilter.CombineRule(new Properties.RegexpPropertyMatcher("name", "Cmp.*"), new Properties.RegexpPropertyMatcher("name", "Bool")));
+f.apply(graph);
+split("name", "BoxLock");
+split("name", "(Con.*)|(loadCon.*)", "[dump_spec]");
\ No newline at end of file
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/layer.xml	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/layer.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -2,60 +2,28 @@
 <!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd">
 <filesystem>
       <folder name="Filters">
-        <file name="Basic Coloring" url="filters/color.filter">
-            <attr name="enabled" boolvalue="true"/>
-        </file>
-        <file name="Matcher Flags Coloring" url="filters/matchingFlags.filter">
-            <attr name="enabled" boolvalue="true"/>
-            <attr name="after" stringvalue="Basic Coloring"/>
-        </file>
-        <file name="Register Coloring" url="filters/register.filter">
-            <attr name="enabled" boolvalue="true"/>
-            <attr name="after" stringvalue="Matcher Flags Coloring"/>
+        <file name="C2 Basic Coloring" url="filters/color.filter">
+            <attr name="enabled" boolvalue="false"/>
         </file>
-        <file name="Extended Coloring" url="filters/extendedColor.filter">
-            <attr name="enabled" boolvalue="true"/>
-            <attr name="after" stringvalue="Register Coloring"/>
-        </file>
-        <file name="Line Coloring" url="filters/linestyle.filter">
-            <attr name="enabled" boolvalue="true"/>
-            <attr name="after" stringvalue="Extended Coloring"/>
+        <file name="C2 Matcher Flags Coloring" url="filters/matchingFlags.filter">
+            <attr name="enabled" boolvalue="false"/>
+            <attr name="after" stringvalue="C2 Basic Coloring"/>
         </file>
-        <file name="Difference Coloring" url="filters/difference.filter">
-            <attr name="enabled" boolvalue="true"/>
-            <attr name="after" stringvalue="Line Coloring"/>
-        </file>
-        <file name="Only Control Flow" url="filters/onlyControlFlow.filter">
+        <file name="C2 Register Coloring" url="filters/register.filter">
             <attr name="enabled" boolvalue="false"/>
-            <attr name="after" stringvalue="Difference Coloring"/>
+            <attr name="after" stringvalue="C2 Matcher Flags Coloring"/>
         </file>
-        <file name="Remove FramePtr, I_O and Return Address" url="filters/remove.filter">
-            <attr name="enabled" boolvalue="true"/>
-            <attr name="after" stringvalue="Only Control Flow"/>
-        </file>
-        <file name="Remove Memory" url="filters/removeMemory.filter">
+        <file name="C2 Only Control Flow" url="filters/onlyControlFlow.filter">
             <attr name="enabled" boolvalue="false"/>
-            <attr name="after" stringvalue="Remove FramePtr, I_O and Return Address"/>
-        </file>
-        <file name="Remove Root Inputs" url="filters/removeRootInputs.filter">
-            <attr name="enabled" boolvalue="true"/>
-            <attr name="after" stringvalue="Remove Memory"/>
+            <attr name="after" stringvalue="C2 Register Coloring"/>
         </file>
-        <file name="Remove Safepoint Inputs" url="filters/removeSafepointInputs.filter">
-            <attr name="enabled" boolvalue="true"/>
-            <attr name="after" stringvalue="Remove Root Inputs"/>
-        </file>
-        <file name="Remove Self Loops" url="filters/removeSelfLoops.filter">
-            <attr name="enabled" boolvalue="true"/>
-            <attr name="after" stringvalue="Remove Safepoint Inputs"/>
+        <file name="C2 Remove Filter" url="filters/remove.filter">
+            <attr name="enabled" boolvalue="false"/>
+            <attr name="after" stringvalue="C2 Only Control Flow"/>
         </file>
-        <file name="Combine" url="filters/combine.filter">
-            <attr name="enabled" boolvalue="true"/>
-            <attr name="after" stringvalue="Remove Self Loops"/>
+        <file name="C2 Structural" url="filters/structural.filter">
+            <attr name="enabled" boolvalue="false"/>
+            <attr name="after" stringvalue="C2 Remove Filter"/>
         </file>
-        <file name="Split" url="filters/split.filter">
-            <attr name="enabled" boolvalue="true"/>
-            <attr name="after" stringvalue="Combine"/>
-        </file>
-    </folder>
+    </folder>	
 </filesystem>
--- a/src/share/tools/IdealGraphVisualizer/Settings/nbproject/project.xml	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Settings/nbproject/project.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -12,7 +12,7 @@
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>1</release-version>
-                        <specification-version>1.4</specification-version>
+                        <specification-version>1.16.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -21,7 +21,7 @@
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>1</release-version>
-                        <specification-version>1.5</specification-version>
+                        <specification-version>1.21.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -29,7 +29,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.11.0.1</specification-version>
+                        <specification-version>7.30.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -37,7 +37,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.9.0.1</specification-version>
+                        <specification-version>8.14.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.lookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.6.1</specification-version>
                     </run-dependency>
                 </dependency>
             </module-dependencies>
--- a/src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/ViewOptionsCategory.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/ViewOptionsCategory.java	Wed Jul 27 17:32:44 2011 -0700
@@ -27,8 +27,8 @@
 import javax.swing.ImageIcon;
 import org.netbeans.spi.options.OptionsCategory;
 import org.netbeans.spi.options.OptionsPanelController;
+import org.openide.util.ImageUtilities;
 import org.openide.util.NbBundle;
-import org.openide.util.Utilities;
 
 /**
  *
@@ -38,7 +38,7 @@
 
     @Override
     public Icon getIcon() {
-        return new ImageIcon(Utilities.loadImage("com/sun/hotspot/igv/settings/settings.gif"));
+        return new ImageIcon(ImageUtilities.loadImage("com/sun/hotspot/igv/settings/settings.gif"));
     }
 
     public String getCategoryName() {
--- a/src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/layer.xml	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/layer.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -2,8 +2,8 @@
 <!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd">
 <filesystem>
     <folder name="OptionsDialog">
-        <file name="Advanced.instance_hidden"/>
-        <file name="General.instance_hidden"/>
+      <!-- <file name="Advanced.instance_hidden"/>
+        <file name="General.instance_hidden"/>-->
         <file name="com-sun-hotspot-igv-settings-ViewOptionsCategory.instance"/>
     </folder>
 </filesystem>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/StructuredText/build.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
+<!-- for some information on what you could do (e.g. targets to override). -->
+<!-- If you delete this file and reopen the project it will be recreated. -->
+<project name="com.sun.hotspot.igv.structuredtext" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project com.sun.hotspot.igv.structuredtext.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/StructuredText/manifest.mf	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+OpenIDE-Module: com.sun.hotspot.igv.structuredtext
+OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/structuredtext/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/StructuredText/nbproject/build-impl.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT  ***
+***         EDIT ../build.xml INSTEAD         ***
+-->
+<project name="com.sun.hotspot.igv.structuredtext-impl" basedir="..">
+    <fail message="Please build using Ant 1.7.1 or higher.">
+        <condition>
+            <not>
+                <antversion atleast="1.7.1"/>
+            </not>
+        </condition>
+    </fail>
+    <property file="nbproject/private/suite-private.properties"/>
+    <property file="nbproject/suite.properties"/>
+    <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
+    <property file="${suite.dir}/nbproject/private/platform-private.properties"/>
+    <property file="${suite.dir}/nbproject/platform.properties"/>
+    <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="name"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{name}" value="${@{value}}"/>
+        </sequential>
+    </macrodef>
+    <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="property"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{property}" value="@{value}"/>
+        </sequential>
+    </macrodef>
+    <property file="${user.properties.file}"/>
+    <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
+        <condition>
+            <not>
+                <contains string="${cluster.path.evaluated}" substring="platform"/>
+            </not>
+        </condition>
+    </fail>
+    <import file="${harness.dir}/build.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/StructuredText/nbproject/genfiles.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,5 @@
+# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
+# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
+nbproject/build-impl.xml.data.CRC32=216fc635
+nbproject/build-impl.xml.script.CRC32=6022dc85
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.45.1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/StructuredText/nbproject/platform.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,129 @@
+# Deprecated since 5.0u1; for compatibility with 5.0:
+disabled.clusters=\
+    apisupport1,\
+    gsf1,\
+    harness,\
+    java2,\
+    nb6.1,\
+    profiler3
+disabled.modules=\
+    org.apache.xml.resolver,\
+    org.netbeans.api.debugger,\
+    org.netbeans.api.xml,\
+    org.netbeans.core.execution,\
+    org.netbeans.core.ide,\
+    org.netbeans.core.multiview,\
+    org.netbeans.core.nativeaccess,\
+    org.netbeans.core.output2,\
+    org.netbeans.insane,\
+    org.netbeans.lib.cvsclient,\
+    org.netbeans.libs.commons_logging,\
+    org.netbeans.libs.freemarker,\
+    org.netbeans.libs.ini4j,\
+    org.netbeans.libs.jna,\
+    org.netbeans.libs.jsch,\
+    org.netbeans.libs.jsr223,\
+    org.netbeans.libs.lucene,\
+    org.netbeans.libs.svnClientAdapter,\
+    org.netbeans.libs.xerces,\
+    org.netbeans.modules.applemenu,\
+    org.netbeans.modules.autoupdate.services,\
+    org.netbeans.modules.autoupdate.ui,\
+    org.netbeans.modules.classfile,\
+    org.netbeans.modules.core.kit,\
+    org.netbeans.modules.db,\
+    org.netbeans.modules.db.core,\
+    org.netbeans.modules.db.drivers,\
+    org.netbeans.modules.db.kit,\
+    org.netbeans.modules.db.mysql,\
+    org.netbeans.modules.db.sql.editor,\
+    org.netbeans.modules.db.sql.visualeditor,\
+    org.netbeans.modules.dbapi,\
+    org.netbeans.modules.defaults,\
+    org.netbeans.modules.diff,\
+    org.netbeans.modules.editor.bookmarks,\
+    org.netbeans.modules.editor.bracesmatching,\
+    org.netbeans.modules.editor.codetemplates,\
+    org.netbeans.modules.editor.completion,\
+    org.netbeans.modules.editor.errorstripe,\
+    org.netbeans.modules.editor.errorstripe.api,\
+    org.netbeans.modules.editor.guards,\
+    org.netbeans.modules.editor.highlights,\
+    org.netbeans.modules.editor.macros,\
+    org.netbeans.modules.editor.plain,\
+    org.netbeans.modules.editor.plain.lib,\
+    org.netbeans.modules.editor.structure,\
+    org.netbeans.modules.extbrowser,\
+    org.netbeans.modules.favorites,\
+    org.netbeans.modules.gototest,\
+    org.netbeans.modules.httpserver,\
+    org.netbeans.modules.ide.kit,\
+    org.netbeans.modules.image,\
+    org.netbeans.modules.javahelp,\
+    org.netbeans.modules.jumpto,\
+    org.netbeans.modules.languages,\
+    org.netbeans.modules.languages.bat,\
+    org.netbeans.modules.languages.diff,\
+    org.netbeans.modules.languages.manifest,\
+    org.netbeans.modules.languages.sh,\
+    org.netbeans.modules.lexer.editorbridge,\
+    org.netbeans.modules.lexer.nbbridge,\
+    org.netbeans.modules.localhistory,\
+    org.netbeans.modules.masterfs,\
+    org.netbeans.modules.mercurial,\
+    org.netbeans.modules.progress.ui,\
+    org.netbeans.modules.project.ant,\
+    org.netbeans.modules.project.libraries,\
+    org.netbeans.modules.projectui,\
+    org.netbeans.modules.projectuiapi,\
+    org.netbeans.modules.properties,\
+    org.netbeans.modules.properties.syntax,\
+    org.netbeans.modules.refactoring.api,\
+    org.netbeans.modules.schema2beans,\
+    org.netbeans.modules.sendopts,\
+    org.netbeans.modules.server,\
+    org.netbeans.modules.servletapi,\
+    org.netbeans.modules.subversion,\
+    org.netbeans.modules.tasklist.kit,\
+    org.netbeans.modules.tasklist.projectint,\
+    org.netbeans.modules.tasklist.todo,\
+    org.netbeans.modules.tasklist.ui,\
+    org.netbeans.modules.templates,\
+    org.netbeans.modules.timers,\
+    org.netbeans.modules.usersguide,\
+    org.netbeans.modules.utilities,\
+    org.netbeans.modules.utilities.project,\
+    org.netbeans.modules.versioning,\
+    org.netbeans.modules.versioning.system.cvss,\
+    org.netbeans.modules.versioning.util,\
+    org.netbeans.modules.web.flyingsaucer,\
+    org.netbeans.modules.xml,\
+    org.netbeans.modules.xml.axi,\
+    org.netbeans.modules.xml.catalog,\
+    org.netbeans.modules.xml.core,\
+    org.netbeans.modules.xml.lexer,\
+    org.netbeans.modules.xml.multiview,\
+    org.netbeans.modules.xml.retriever,\
+    org.netbeans.modules.xml.schema.completion,\
+    org.netbeans.modules.xml.schema.model,\
+    org.netbeans.modules.xml.tax,\
+    org.netbeans.modules.xml.text,\
+    org.netbeans.modules.xml.tools,\
+    org.netbeans.modules.xml.wsdl.model,\
+    org.netbeans.modules.xml.xam,\
+    org.netbeans.modules.xml.xdm,\
+    org.netbeans.modules.xsl,\
+    org.netbeans.spi.debugger.ui,\
+    org.netbeans.spi.editor.hints,\
+    org.netbeans.spi.navigator,\
+    org.netbeans.spi.palette,\
+    org.netbeans.spi.tasklist,\
+    org.netbeans.spi.viewmodel,\
+    org.netbeans.swing.dirchooser,\
+    org.openide.compat,\
+    org.openide.util.enumerations
+enabled.clusters=\
+    ide9,\
+    platform8
+nbjdk.active=default
+nbplatform.active=default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/StructuredText/nbproject/project.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,2 @@
+javac.source=1.5
+javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/StructuredText/nbproject/project.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.apisupport.project</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
+            <code-name-base>com.sun.hotspot.igv.structuredtext</code-name-base>
+            <suite-component/>
+            <module-dependencies/>
+            <public-packages>
+                <package>com.sun.hotspot.igv.structuredtext</package>
+                <package>com.sun.hotspot.igv.structuredtext.services</package>
+            </public-packages>
+        </data>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/StructuredText/nbproject/suite.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,1 @@
+suite.dir=${basedir}/..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/StructuredText/src/com/sun/hotspot/igv/structuredtext/Bundle.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,1 @@
+OpenIDE-Module-Name=StructuredText
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/StructuredText/src/com/sun/hotspot/igv/structuredtext/Element.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,83 @@
+/*
+ * 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.sun.hotspot.igv.structuredtext;
+
+import com.sun.hotspot.igv.structuredtext.services.ElementVisitor;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import javax.swing.text.Style;
+import javax.swing.text.StyleContext;
+
+/**
+ *
+ * @author Thomas
+ */
+public abstract class Element {
+    
+    private Set<Object> source;
+    private Style style;
+    private Style highlightedStyle;
+    
+    public Element() {
+        source = new HashSet<Object>();
+        style = null;
+        highlightedStyle = null;
+    }
+    
+    public Style getStyle() {
+        return style;
+    }
+
+    public Style getHighlightedStyle() {
+        return highlightedStyle;
+    }
+    
+    public void setStyle(Style style) {
+        this.style = style;
+    }
+
+    public void setHighlightedStyle(Style style) {
+        this.highlightedStyle = style;
+    }
+    
+    public void setStyleRecursive(Style style) {
+        this.style = style;
+    }
+
+    public void setHighlightedStyleRecursive(Style style) {
+        this.highlightedStyle = style;
+    }
+    
+    public Set<Object> getSource() {
+        return Collections.unmodifiableSet(source);
+    }
+    
+    public void addSource(Object o) {
+        source.add(o);
+    }
+    
+    public abstract void accept(ElementVisitor visitor);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/StructuredText/src/com/sun/hotspot/igv/structuredtext/MultiElement.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,139 @@
+/*
+ * 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.sun.hotspot.igv.structuredtext;
+
+import com.sun.hotspot.igv.structuredtext.services.ElementVisitor;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import javax.swing.text.Style;
+
+/**
+ *
+ * @author Thomas
+ */
+public class MultiElement extends Element {
+
+    private List<Element> children;
+    private String foldString;
+    
+    public MultiElement() {
+        this((String)null);
+    }
+       
+    public MultiElement(String foldString) {
+        this(foldString, null);
+    }
+    
+    public MultiElement(Style style) {
+        this(null, style);
+    }
+    
+    public MultiElement(String foldString, Style style) {
+        setStyle(style);
+        this.foldString = foldString;
+        children = new ArrayList<Element>();
+    }
+    
+    public void print(String s) {
+        print(s, null);
+    }
+
+    @Override
+    public void setStyleRecursive(Style style) {
+        super.setStyleRecursive(style);
+        for(Element elem : this.getChildren()) {
+            elem.setStyleRecursive(style);
+        }
+    }
+
+    @Override
+    public void setHighlightedStyleRecursive(Style style) {
+        super.setStyleRecursive(style);
+        for(Element elem : this.getChildren()) {
+            elem.setHighlightedStyleRecursive(style);
+        }
+    }
+    
+    public void print(String s, Object source) {
+        if (s == null) {
+            s = "";
+        }
+        SimpleElement elem = new SimpleElement(s);
+        if(source != null) {
+            elem.addSource(source);
+        }
+        addChild(elem);
+    }
+
+    public void print(String s, Object source, int padding) {
+        if (s == null) {
+            s = "";
+        }
+        StringBuilder sb = new StringBuilder(s);
+        while (sb.length() < padding) {
+            sb.insert(0, ' ');
+        }
+        print(sb.toString(), source);
+    }
+
+    public void println() {
+        println("");
+    }
+    
+    public void println(String s) {
+        print(s + "\n");
+    }
+    
+    public void println(String s, Object source) {
+        print(s + "\n", source);
+    }
+    
+    
+    public void println(String s, Object source, int padding) {
+        print(s + "\n", source, padding);
+    }
+    
+    public void addChild(Element element) {
+        assert element != null;
+        this.children.add(element);
+    }
+    
+    public String getFoldString() {
+        return foldString;
+    }
+    
+    public void setFoldString(String s) {
+        this.foldString = s;
+    }
+    
+    public List<Element> getChildren() {
+        return Collections.unmodifiableList(children);
+    }
+    
+    public void accept(ElementVisitor visitor) {
+        visitor.visit(this);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/StructuredText/src/com/sun/hotspot/igv/structuredtext/Range.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,57 @@
+/*
+ * 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.sun.hotspot.igv.structuredtext;
+
+/**
+ *
+ * @author Thomas
+ */
+public class Range {
+    
+    private int start;
+    private int length;
+    
+    public Range(int start, int length) {
+        this.start = start;
+        this.length = length;
+    }
+    
+    public int getStart() {
+        return start;
+    }
+    
+    public boolean overlaps(Range r2) {
+        if(start < r2.start) {
+            return start + length > r2.start;
+        } else {
+            return r2.start + r2.length > start;
+        }
+    }
+    
+    public int getLength() {
+        return length;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/StructuredText/src/com/sun/hotspot/igv/structuredtext/SimpleElement.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,78 @@
+/*
+ * 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.sun.hotspot.igv.structuredtext;
+
+import com.sun.hotspot.igv.structuredtext.services.ElementVisitor;
+import javax.swing.text.Style;
+import javax.swing.text.StyleContext;
+
+/**
+ *
+ * @author Thomas
+ */
+public class SimpleElement extends Element {
+
+    public static final Element EMPTY = new SimpleElement("");
+    public static final Element LN = new SimpleElement("\n");
+    public static final Element TAB = new SimpleElement("\t");
+    
+    private String text;
+    
+    public SimpleElement(String s) {
+        this(s, null);
+    }
+    
+    public SimpleElement(String s, Style style) {
+        setText(s);
+        setStyle(style);
+        assert text != null;
+    }
+    
+    private static String addPadding(String s, int minLength) {
+        
+        StringBuilder sb = new StringBuilder(s);
+        while(sb.length() < minLength) {
+            sb.insert(0, ' ');
+        }
+        return sb.toString();
+    }
+    
+    public SimpleElement(String s, int length) {
+        this(addPadding(s, length));
+    }
+    
+    
+    public String getText() {
+        return text;
+    }
+    
+    public void setText(String s) {
+        this.text = s;
+    }
+    
+    public void accept(ElementVisitor visitor) {
+        visitor.visit(this);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/StructuredText/src/com/sun/hotspot/igv/structuredtext/StructuredText.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,112 @@
+/*
+ * 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.sun.hotspot.igv.structuredtext;
+
+import com.sun.hotspot.igv.structuredtext.services.ElementVisitor;
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ *
+ * @author Thomas
+ */
+public class StructuredText extends MultiElement {
+    
+    private String name;
+    
+    public StructuredText(String name) {
+        this.name = name;
+    }
+    
+    public String getName() {
+        return name;
+    }
+    
+    public Element findElementAt(final int searchIndex) {
+        
+        final Element[] result = new Element[1];
+        this.accept(new ElementVisitor() {
+            
+            private int index;
+            
+            @Override
+            public void visit(MultiElement element) {
+                int startIndex = index;
+                super.visit(element);
+            }
+
+            @Override
+            public void visit(SimpleElement element) {
+                if(searchIndex >= index && searchIndex < index + element.getText().length()) {
+                    assert result[0] == null;
+                    result[0] = element;
+                }
+                index += element.getText().length();
+            }
+        });
+        
+        return result[0];
+    }
+    
+    public Map<Element, Range> calculateRanges() {
+        
+        final Map<Element, Range> result = new HashMap<Element, Range>();
+        
+        this.accept(new ElementVisitor() {
+            
+            private int index;
+            
+            @Override
+            public void visit(MultiElement element) {
+                int startIndex = index;
+                super.visit(element);
+                result.put(element, new Range(startIndex, index - startIndex));
+            }
+
+            @Override
+            public void visit(SimpleElement element) {
+                result.put(element, new Range(index, element.getText().length()));
+                index += element.getText().length();
+            }
+        });
+        
+        
+        return result;
+        
+    }
+    
+    public String convertToString() {
+        final StringBuilder result = new StringBuilder();
+        this.accept(new ElementVisitor() {
+            @Override
+            public void visit(SimpleElement element) {
+                result.append(element.getText());
+            }
+        }
+        );
+        return result.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/StructuredText/src/com/sun/hotspot/igv/structuredtext/ToolTipProvider.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,35 @@
+/*
+ * 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.sun.hotspot.igv.structuredtext;
+
+/**
+ *
+ * @author thomas
+ */
+public interface ToolTipProvider {
+
+        String getToolTip();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/StructuredText/src/com/sun/hotspot/igv/structuredtext/services/ElementVisitor.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,44 @@
+/*
+ * 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.sun.hotspot.igv.structuredtext.services;
+
+import com.sun.hotspot.igv.structuredtext.Element;
+import com.sun.hotspot.igv.structuredtext.MultiElement;
+import com.sun.hotspot.igv.structuredtext.SimpleElement;
+
+/**
+ *
+ * @author Thomas
+ */
+public abstract class ElementVisitor {
+
+    public void visit(MultiElement element) {
+        
+        for(Element e : element.getChildren()) {
+            e.accept(this);
+        }
+    }
+    public abstract void visit(SimpleElement element);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/TextEditor/build.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
+<!-- for some information on what you could do (e.g. targets to override). -->
+<!-- If you delete this file and reopen the project it will be recreated. -->
+<project name="com.sun.hotspot.igv.texteditor" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project com.sun.hotspot.igv.texteditor.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/TextEditor/manifest.mf	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+OpenIDE-Module: com.sun.hotspot.igv.texteditor
+OpenIDE-Module-Layer: com/sun/hotspot/igv/texteditor/layer.xml
+OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/texteditor/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/TextEditor/nbproject/build-impl.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT  ***
+***         EDIT ../build.xml INSTEAD         ***
+-->
+<project name="com.sun.hotspot.igv.texteditor-impl" basedir="..">
+    <fail message="Please build using Ant 1.7.1 or higher.">
+        <condition>
+            <not>
+                <antversion atleast="1.7.1"/>
+            </not>
+        </condition>
+    </fail>
+    <property file="nbproject/private/suite-private.properties"/>
+    <property file="nbproject/suite.properties"/>
+    <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
+    <property file="${suite.dir}/nbproject/private/platform-private.properties"/>
+    <property file="${suite.dir}/nbproject/platform.properties"/>
+    <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="name"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{name}" value="${@{value}}"/>
+        </sequential>
+    </macrodef>
+    <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="property"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{property}" value="@{value}"/>
+        </sequential>
+    </macrodef>
+    <property file="${user.properties.file}"/>
+    <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
+        <condition>
+            <not>
+                <contains string="${cluster.path.evaluated}" substring="platform"/>
+            </not>
+        </condition>
+    </fail>
+    <import file="${harness.dir}/build.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/TextEditor/nbproject/genfiles.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,5 @@
+# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
+# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
+nbproject/build-impl.xml.data.CRC32=2b80dbe4
+nbproject/build-impl.xml.script.CRC32=122053f6
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.45.1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/TextEditor/nbproject/platform.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,129 @@
+# Deprecated since 5.0u1; for compatibility with 5.0:
+disabled.clusters=\
+    apisupport1,\
+    gsf1,\
+    harness,\
+    java2,\
+    nb6.1,\
+    profiler3
+disabled.modules=\
+    org.apache.xml.resolver,\
+    org.netbeans.api.debugger,\
+    org.netbeans.api.xml,\
+    org.netbeans.core.execution,\
+    org.netbeans.core.ide,\
+    org.netbeans.core.multiview,\
+    org.netbeans.core.nativeaccess,\
+    org.netbeans.core.output2,\
+    org.netbeans.insane,\
+    org.netbeans.lib.cvsclient,\
+    org.netbeans.libs.commons_logging,\
+    org.netbeans.libs.freemarker,\
+    org.netbeans.libs.ini4j,\
+    org.netbeans.libs.jna,\
+    org.netbeans.libs.jsch,\
+    org.netbeans.libs.jsr223,\
+    org.netbeans.libs.lucene,\
+    org.netbeans.libs.svnClientAdapter,\
+    org.netbeans.libs.xerces,\
+    org.netbeans.modules.applemenu,\
+    org.netbeans.modules.autoupdate.services,\
+    org.netbeans.modules.autoupdate.ui,\
+    org.netbeans.modules.classfile,\
+    org.netbeans.modules.core.kit,\
+    org.netbeans.modules.db,\
+    org.netbeans.modules.db.core,\
+    org.netbeans.modules.db.drivers,\
+    org.netbeans.modules.db.kit,\
+    org.netbeans.modules.db.mysql,\
+    org.netbeans.modules.db.sql.editor,\
+    org.netbeans.modules.db.sql.visualeditor,\
+    org.netbeans.modules.dbapi,\
+    org.netbeans.modules.defaults,\
+    org.netbeans.modules.diff,\
+    org.netbeans.modules.editor.bookmarks,\
+    org.netbeans.modules.editor.bracesmatching,\
+    org.netbeans.modules.editor.codetemplates,\
+    org.netbeans.modules.editor.completion,\
+    org.netbeans.modules.editor.errorstripe,\
+    org.netbeans.modules.editor.errorstripe.api,\
+    org.netbeans.modules.editor.guards,\
+    org.netbeans.modules.editor.highlights,\
+    org.netbeans.modules.editor.macros,\
+    org.netbeans.modules.editor.plain,\
+    org.netbeans.modules.editor.plain.lib,\
+    org.netbeans.modules.editor.structure,\
+    org.netbeans.modules.extbrowser,\
+    org.netbeans.modules.favorites,\
+    org.netbeans.modules.gototest,\
+    org.netbeans.modules.httpserver,\
+    org.netbeans.modules.ide.kit,\
+    org.netbeans.modules.image,\
+    org.netbeans.modules.javahelp,\
+    org.netbeans.modules.jumpto,\
+    org.netbeans.modules.languages,\
+    org.netbeans.modules.languages.bat,\
+    org.netbeans.modules.languages.diff,\
+    org.netbeans.modules.languages.manifest,\
+    org.netbeans.modules.languages.sh,\
+    org.netbeans.modules.lexer.editorbridge,\
+    org.netbeans.modules.lexer.nbbridge,\
+    org.netbeans.modules.localhistory,\
+    org.netbeans.modules.masterfs,\
+    org.netbeans.modules.mercurial,\
+    org.netbeans.modules.progress.ui,\
+    org.netbeans.modules.project.ant,\
+    org.netbeans.modules.project.libraries,\
+    org.netbeans.modules.projectui,\
+    org.netbeans.modules.projectuiapi,\
+    org.netbeans.modules.properties,\
+    org.netbeans.modules.properties.syntax,\
+    org.netbeans.modules.refactoring.api,\
+    org.netbeans.modules.schema2beans,\
+    org.netbeans.modules.sendopts,\
+    org.netbeans.modules.server,\
+    org.netbeans.modules.servletapi,\
+    org.netbeans.modules.subversion,\
+    org.netbeans.modules.tasklist.kit,\
+    org.netbeans.modules.tasklist.projectint,\
+    org.netbeans.modules.tasklist.todo,\
+    org.netbeans.modules.tasklist.ui,\
+    org.netbeans.modules.templates,\
+    org.netbeans.modules.timers,\
+    org.netbeans.modules.usersguide,\
+    org.netbeans.modules.utilities,\
+    org.netbeans.modules.utilities.project,\
+    org.netbeans.modules.versioning,\
+    org.netbeans.modules.versioning.system.cvss,\
+    org.netbeans.modules.versioning.util,\
+    org.netbeans.modules.web.flyingsaucer,\
+    org.netbeans.modules.xml,\
+    org.netbeans.modules.xml.axi,\
+    org.netbeans.modules.xml.catalog,\
+    org.netbeans.modules.xml.core,\
+    org.netbeans.modules.xml.lexer,\
+    org.netbeans.modules.xml.multiview,\
+    org.netbeans.modules.xml.retriever,\
+    org.netbeans.modules.xml.schema.completion,\
+    org.netbeans.modules.xml.schema.model,\
+    org.netbeans.modules.xml.tax,\
+    org.netbeans.modules.xml.text,\
+    org.netbeans.modules.xml.tools,\
+    org.netbeans.modules.xml.wsdl.model,\
+    org.netbeans.modules.xml.xam,\
+    org.netbeans.modules.xml.xdm,\
+    org.netbeans.modules.xsl,\
+    org.netbeans.spi.debugger.ui,\
+    org.netbeans.spi.editor.hints,\
+    org.netbeans.spi.navigator,\
+    org.netbeans.spi.palette,\
+    org.netbeans.spi.tasklist,\
+    org.netbeans.spi.viewmodel,\
+    org.netbeans.swing.dirchooser,\
+    org.openide.compat,\
+    org.openide.util.enumerations
+enabled.clusters=\
+    ide9,\
+    platform8
+nbjdk.active=default
+nbplatform.active=default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/TextEditor/nbproject/project.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,2 @@
+javac.source=1.5
+javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/TextEditor/nbproject/project.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.apisupport.project</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
+            <code-name-base>com.sun.hotspot.igv.texteditor</code-name-base>
+            <suite-component/>
+            <module-dependencies>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.data</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.selectioncoordinator</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.structuredtext</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.editor</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>3</release-version>
+                        <specification-version>1.42.2.3.9.2</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.editor.fold</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.8</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.editor.lib</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>3</release-version>
+                        <specification-version>3.8.1.13.9</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.editor.lib2</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.11.2.2</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.text</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>6.18</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.12.0.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.windows</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>6.20</specification-version>
+                    </run-dependency>
+                </dependency>
+            </module-dependencies>
+            <public-packages>
+                <package>com.sun.hotspot.igv.texteditor</package>
+            </public-packages>
+        </data>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/TextEditor/nbproject/suite.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,1 @@
+suite.dir=${basedir}/..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/TextEditor/src/com/sun/hotspot/igv/texteditor/Bundle.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,2 @@
+
+OpenIDE-Module-Name=TextEditor
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/TextEditor/src/com/sun/hotspot/igv/texteditor/SyntaxLayer.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,327 @@
+/*
+ * 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.sun.hotspot.igv.texteditor;
+
+import com.sun.hotspot.igv.data.ChangedListener;
+import com.sun.hotspot.igv.selectioncoordinator.SelectionCoordinator;
+import com.sun.hotspot.igv.structuredtext.MultiElement;
+import com.sun.hotspot.igv.structuredtext.SimpleElement;
+import com.sun.hotspot.igv.structuredtext.StructuredText;
+import com.sun.hotspot.igv.structuredtext.Element;
+import com.sun.hotspot.igv.structuredtext.Range;
+import com.sun.hotspot.igv.structuredtext.ToolTipProvider;
+import com.sun.hotspot.igv.structuredtext.services.ElementVisitor;
+import java.awt.Color;
+import java.awt.Cursor;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Stack;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.Style;
+import javax.swing.text.StyleConstants;
+import javax.swing.text.StyleContext;
+import org.netbeans.spi.editor.highlighting.HighlightsLayerFactory;
+import org.netbeans.spi.editor.highlighting.HighlightsSequence;
+import org.netbeans.spi.editor.highlighting.support.AbstractHighlightsContainer;
+
+/**
+ *
+ * @author Thomas
+ */
+public class SyntaxLayer extends AbstractHighlightsContainer implements ChangedListener<SelectionCoordinator> {
+
+    private HighlightsLayerFactory.Context context;
+
+    public SyntaxLayer(final HighlightsLayerFactory.Context context) {
+        this.context = context;
+
+        context.getDocument().addDocumentListener(new DocumentListener() {
+
+            public void insertUpdate(DocumentEvent arg0) {
+                update();
+            }
+
+            public void removeUpdate(DocumentEvent arg0) {
+            }
+
+            public void changedUpdate(DocumentEvent arg0) {
+            }
+        });
+
+        SelectionCoordinator.getInstance().getSelectedChangedEvent().addListener(this);
+        SelectionCoordinator.getInstance().getHighlightedChangedEvent().addListener(this);
+
+        context.getComponent().addMouseMotionListener(new MouseMotionListener() {
+
+            public void mouseDragged(MouseEvent e) {
+            }
+
+            public void mouseMoved(MouseEvent e) {
+                // [tw] hack to prevent sidebar mouse over
+                if (e.getPoint().getX() < 15) return;
+
+                int index = context.getComponent().viewToModel(e.getPoint());
+                Element elem = indexToElement(index);
+                if (elem != null) {
+                    Set<Object> highlightedSource = new HashSet<Object>(elem.getSource());
+                    SelectionCoordinator.getInstance().setHighlightedObjects(highlightedSource);
+                    context.getComponent().setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
+                }
+            }
+        });
+
+        context.getComponent().addMouseListener(new MouseListener() {
+
+            public void mouseClicked(MouseEvent e) {
+                
+                int index = context.getComponent().viewToModel(e.getPoint());
+                Element elem = indexToElement(index);
+                if (elem != null) {
+                    Set<Object> selectedSource = new HashSet<Object>(elem.getSource());
+
+                    for (Object o : selectedSource) {
+                        if (o instanceof ToolTipProvider) {
+                            String toolTip = ((ToolTipProvider) o).getToolTip();
+                        }
+                    }
+
+                    if ((e.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) != 0) {
+
+                        SelectionCoordinator.getInstance().addAllSelected(selectedSource);
+                    } else {
+                        SelectionCoordinator.getInstance().setSelectedObjects(selectedSource);
+                    }
+                    context.getComponent().setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
+                } else {
+                    context.getComponent().setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR));
+
+                }
+            }
+
+            public void mousePressed(MouseEvent e) {
+            }
+
+            public void mouseReleased(MouseEvent e) {
+            }
+
+            public void mouseEntered(MouseEvent e) {
+            }
+
+            public void mouseExited(MouseEvent e) {
+                SelectionCoordinator.getInstance().setHighlightedObjects(new HashSet<Object>());
+            }
+        });
+    }
+
+    public void changed(SelectionCoordinator source) {
+        update();
+    }
+
+    private void update() {
+        fireHighlightsChange(0, context.getDocument().getLength());
+    }
+
+    private Element indexToElement(int index) {
+        StructuredText text = (StructuredText) context.getDocument().getProperty(StructuredText.class);
+        if (text == null) {
+            return null;
+        }
+        return text.findElementAt(index);
+    }
+
+    private static class HighlightsRange {
+
+        private int start;
+        private int end;
+        private AttributeSet attributes;
+
+        public HighlightsRange(int start, int length, AttributeSet attributes) {
+            this.start = start;
+            this.end = start + length;
+            this.attributes = attributes;
+        }
+
+        public int getStart() {
+            return start;
+        }
+
+        public int getEnd() {
+            return end;
+        }
+
+        public AttributeSet getAttributes() {
+            return attributes;
+        }
+    }
+
+    private static class HighlightsSequenceImpl implements HighlightsSequence {
+
+        private List<HighlightsRange> ranges;
+        private int currentIndex;
+
+        public HighlightsSequenceImpl() {
+            this(new ArrayList<HighlightsRange>());
+        }
+
+        public HighlightsSequenceImpl(List<HighlightsRange> ranges) {
+            this.ranges = ranges;
+            this.currentIndex = -1;
+        }
+
+        public boolean moveNext() {
+            currentIndex++;
+            return currentIndex < ranges.size();
+        }
+
+        public int getStartOffset() {
+            return ranges.get(currentIndex).getStart();
+        }
+
+        public int getEndOffset() {
+            return ranges.get(currentIndex).getEnd();
+        }
+
+        public AttributeSet getAttributes() {
+            return ranges.get(currentIndex).getAttributes();
+        }
+    }
+
+    private boolean intersects(Set<Object> s1, Set<Object> s2) {
+        for (Object o : s1) {
+            if (s2.contains(o)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public HighlightsSequence getHighlights(final int start, final int end) {
+
+        StructuredText text = (StructuredText) context.getDocument().getProperty(StructuredText.class);
+        if (text == null) {
+            return new HighlightsSequenceImpl();
+        }
+        final Map<Element, Range> ranges = text.calculateRanges();
+        final List<HighlightsRange> highlightsRanges = new ArrayList<HighlightsRange>();
+        final Range baseRange = new Range(start, end - start);
+
+        text.accept(new ElementVisitor() {
+            
+            private Stack<Style> styleStack = new Stack<Style>();
+            private Stack<Style> highlightedStyleStack = new Stack<Style>();
+            private Stack<MultiElement> parentElements = new Stack<MultiElement>();
+            
+            @Override
+            public void visit(MultiElement element) {
+                Style curStyle = element.getStyle();
+                Style curHighlightedStyle = element.getHighlightedStyle();
+                if(curStyle != null) {
+                    styleStack.push(curStyle);
+                }
+                if (curHighlightedStyle != null) {
+                    highlightedStyleStack.push(curHighlightedStyle);
+                }
+                parentElements.push(element);
+                super.visit(element);
+                if(curStyle != null) {
+                    styleStack.pop();
+                }
+                if (curHighlightedStyle != null) {
+                    highlightedStyleStack.pop();
+                }
+                parentElements.pop();
+            }
+            
+
+            @Override
+            public void visit(SimpleElement element) {
+                Range curRange = ranges.get(element);
+                if (baseRange.overlaps(curRange)) {
+                    Style style = element.getStyle();
+                    if(style == null) {
+                        if(styleStack.size() > 0) {
+                            style = styleStack.peek();
+                        } else {
+                            style = StyleContext.getDefaultStyleContext().getStyle(StyleContext.DEFAULT_STYLE);
+                            StyleConstants.setBackground(style, Color.WHITE);
+                        }
+                    }
+                    
+                    
+                    Style highlightedStyle = element.getHighlightedStyle();
+                    if (highlightedStyle == null) {
+                        if (highlightedStyleStack.size() > 0) {
+                            highlightedStyle = highlightedStyleStack.peek();
+                        }
+                    }
+
+                    Set<Object> highlightedSource = SelectionCoordinator.getInstance().getHighlightedObjects();
+                    if (highlightedSource != null) {
+                        
+                        boolean doesIntersect = intersects(element.getSource(), highlightedSource);
+                        for (MultiElement parentElement : parentElements) {
+                            if (doesIntersect) {
+                                break;
+                            }
+
+                            doesIntersect = intersects(parentElement.getSource(), highlightedSource);
+                        }
+
+                        if (doesIntersect) {
+
+                            if (highlightedStyle != null) {
+                                style = highlightedStyle;
+                            } else {
+                                style = StyleContext.getDefaultStyleContext().addStyle(null, style);
+                                Color bg = StyleConstants.getBackground(style);
+                                Color fg = StyleConstants.getForeground(style);
+                                StyleConstants.setBackground(style, new Color(255 - bg.getRed(), 255 - bg.getGreen(), 255 - bg.getBlue()));
+                                StyleConstants.setForeground(style, new Color(255 - fg.getRed(), 255 - fg.getGreen(), 255 - fg.getBlue()));
+                            }
+                        }
+                    }
+
+                    Set<Object> selectedSource = SelectionCoordinator.getInstance().getSelectedObjects();
+                    if (selectedSource != null && intersects(element.getSource(), selectedSource)) {
+                        style = StyleContext.getDefaultStyleContext().addStyle(null, style);
+                        StyleConstants.setBold(style, true);
+                    }
+
+                    highlightsRanges.add(new HighlightsRange(curRange.getStart(), curRange.getLength(), style));
+                }
+            }
+        });
+
+        return new HighlightsSequenceImpl(highlightsRanges);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/TextEditor/src/com/sun/hotspot/igv/texteditor/TextEditor.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,154 @@
+/*
+ * 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.sun.hotspot.igv.texteditor;
+
+import com.sun.hotspot.igv.structuredtext.Element;
+import com.sun.hotspot.igv.structuredtext.MultiElement;
+import com.sun.hotspot.igv.structuredtext.SimpleElement;
+import com.sun.hotspot.igv.structuredtext.StructuredText;
+import com.sun.hotspot.igv.structuredtext.services.ElementVisitor;
+import java.awt.Component;
+import java.util.HashSet;
+import java.util.Set;
+import javax.swing.JEditorPane;
+import javax.swing.SwingUtilities;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Document;
+import javax.swing.text.Position;
+import javax.swing.text.SimpleAttributeSet;
+import org.netbeans.modules.editor.NbEditorDocument;
+import org.netbeans.modules.editor.NbEditorUtilities;
+import org.openide.text.Annotation;
+import org.openide.text.Line;
+import org.openide.util.Exceptions;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class TextEditor {
+    
+    private JEditorPane editorPane;
+    private Component component;
+    private Set<Annotation> addedAnnotations;
+    
+    public TextEditor() {
+        editorPane = new JEditorPane();
+        component = createEditor(editorPane);
+        addedAnnotations = new HashSet<Annotation>();
+        
+    }
+    
+    public Component getComponent() {
+        return component;
+    }
+
+    public void setStructuredText(StructuredText text) {
+        assert text != null;
+        
+        setStructuredText(text, null);
+    }
+    
+    public void setStructuredText(final StructuredText text, final Element focusedElement) {
+        
+        assert text != null;
+
+        SwingUtilities.invokeLater(new Runnable() {
+
+            public void run() {
+                Document doc = editorPane.getDocument();
+                doc.putProperty(StructuredText.class, text);
+
+                for (Annotation a : addedAnnotations) {
+                    ((NbEditorDocument) editorPane.getDocument()).removeAnnotation(a);
+                }
+
+                try {
+                    editorPane.getDocument().remove(0, editorPane.getDocument().getLength());
+                    editorPane.getDocument().insertString(0, text.convertToString(), SimpleAttributeSet.EMPTY);
+
+                    text.accept(new ElementVisitor() {
+
+                        private int pos = 0;
+
+                        private void checkForFocus(Element element) {
+                            if (element == focusedElement) {
+                                editorPane.setCaretPosition(pos);
+                            }
+                        }
+
+                        @Override
+                        public void visit(MultiElement element) {
+                            super.visit(element);
+                            checkForFocus(element);
+                        }
+
+                        @Override
+                        public void visit(SimpleElement element) {
+                            checkForFocus(element);
+                            for (Object o : element.getSource()) {
+                                if (o instanceof Annotation) {
+                                    Annotation a = (Annotation) o;
+                                    final Line line = NbEditorUtilities.getLine(editorPane.getDocument(), pos, false);
+
+                                    ((NbEditorDocument) editorPane.getDocument()).addAnnotation(new PositionImpl(pos), element.getText().length(), a);
+                                    addedAnnotations.add(a);
+                                }
+                            }
+                            pos += element.getText().length();
+                        }
+
+                        class PositionImpl implements Position {
+
+                            private int position;
+
+                            public PositionImpl(int position) {
+                                this.position = position;
+                            }
+
+                            public int getOffset() {
+                                return position;
+                            }
+                        }
+                    });
+
+                } catch (BadLocationException ex) {
+                    Exceptions.printStackTrace(ex);
+                }
+                
+            }
+        });
+       
+    }
+
+    private Component createEditor(JEditorPane pane) {
+        TextEditorKit kit = new TextEditorKit();
+        pane.setEditable(false);
+        NbEditorDocument doc = (NbEditorDocument) kit.createDefaultDocument();
+        pane.setEditorKit(kit);
+        pane.setDocument(doc);
+        return doc.createEditor(pane);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/TextEditor/src/com/sun/hotspot/igv/texteditor/TextEditorKit.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package com.sun.hotspot.igv.texteditor;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.swing.Action;
+import org.netbeans.editor.BaseDocument;
+import org.netbeans.modules.editor.NbEditorKit;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class TextEditorKit extends NbEditorKit {
+
+    public static final String MIME_TYPE = "text/text-igv";
+    
+    /**
+     * Actions to be not available in the editor.
+     */
+    private static final String[] ACTION_FILTER = {
+        NbEditorKit.shiftLineLeftAction,
+        NbEditorKit.shiftLineRightAction,
+        NbEditorKit.jumpListNextAction,
+        NbEditorKit.jumpListNextComponentAction,
+        NbEditorKit.jumpListPrevAction,
+        NbEditorKit.jumpListPrevComponentAction,
+        NbEditorKit.pasteAction,
+        NbEditorKit.removeLineAction,
+        NbEditorKit.cutAction,
+        NbEditorKit.findAction,
+        NbEditorKit.findNextAction,
+        NbEditorKit.findPreviousAction,
+        NbEditorKit.toggleHighlightSearchAction,
+        NbEditorKit.findSelectionAction,
+        "jump-list-last-edit"
+    };
+    
+    @Override
+    protected Action[] createActions() {
+        Action[] actions = super.createActions();
+        List<Action> returnedActions = new ArrayList<Action>();
+        for(Action a : actions) {
+            System.out.println("action: " + a.getValue(Action.NAME));
+            
+            boolean found = false;
+            for(String s : ACTION_FILTER) {
+                if(s.equals(a.getValue(Action.NAME))) {
+                    found = true;
+                }
+            }
+            if(!found) {
+                returnedActions.add(a);
+            }
+        }
+        
+        Action[] result = new Action[returnedActions.size()];
+        for(int i=0; i<returnedActions.size(); i++) {
+            result[i] = returnedActions.get(i);
+        }
+        
+        return result;
+    }
+
+    @Override
+    protected void initDocument(BaseDocument doc) {
+        super.initDocument(doc);
+        System.out.println("Initializing document: " + doc);
+        
+    }
+
+    @Override
+    public String getContentType() {
+        return MIME_TYPE;
+    }
+    
+    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/TextEditor/src/com/sun/hotspot/igv/texteditor/TextFoldManager.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.texteditor;
+
+import com.sun.hotspot.igv.structuredtext.MultiElement;
+import com.sun.hotspot.igv.structuredtext.SimpleElement;
+import javax.swing.event.DocumentEvent;
+import javax.swing.text.BadLocationException;
+import org.netbeans.api.editor.fold.Fold;
+import org.netbeans.spi.editor.fold.FoldHierarchyTransaction;
+import org.netbeans.spi.editor.fold.FoldManager;
+import org.netbeans.spi.editor.fold.FoldOperation;
+import com.sun.hotspot.igv.structuredtext.Element;
+import com.sun.hotspot.igv.structuredtext.Range;
+import com.sun.hotspot.igv.structuredtext.StructuredText;
+import com.sun.hotspot.igv.structuredtext.services.ElementVisitor;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Logger;
+import javax.swing.text.Document;
+import org.netbeans.api.editor.fold.FoldType;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class TextFoldManager implements FoldManager {
+
+    private FoldOperation operation;
+    private final FoldType defaultFoldType = new FoldType("default");
+    private Set<Fold> currentFolds;
+
+    public TextFoldManager() {
+        currentFolds = new HashSet<Fold>();
+    }
+
+    public void init(FoldOperation operation) {
+        this.operation = operation;
+    }
+
+    public void initFolds(final FoldHierarchyTransaction transaction) {
+    }
+
+    private void update(Document document, final FoldHierarchyTransaction transaction) {
+
+        
+        StructuredText text = (StructuredText) document.getProperty(StructuredText.class);
+        if (text == null) {
+            // No StructuredText object behind the document object.
+            return;
+        }
+        
+        if(document.getLength() == 0) {
+            return;
+        }
+        
+        final Map<Element, Range> ranges = text.calculateRanges();
+        currentFolds.clear();
+
+        text.accept(new ElementVisitor() {
+            @Override
+            public void visit(MultiElement element) {
+                super.visit(element);
+                Range curRange = ranges.get(element);
+
+                if (element.getFoldString() != null) {
+                    try {
+                        Fold f = operation.addToHierarchy(defaultFoldType, element.getFoldString(), false,
+                                curRange.getStart(), curRange.getStart() + curRange.getLength(), 0, 0,
+                                null, transaction);
+                        currentFolds.add(f);
+                    } catch (BadLocationException ex) {
+                        assert false : "Structured text not in sync with document content " + ex.getStackTrace();
+                    }
+                }
+            }
+
+            @Override
+            public void visit(SimpleElement element) {
+            }
+        });
+    }
+
+    public void insertUpdate(DocumentEvent event, FoldHierarchyTransaction transaction) {
+        update(event.getDocument(), transaction);
+    }
+
+    public void removeUpdate(DocumentEvent event, FoldHierarchyTransaction transaction) {
+        update(event.getDocument(), transaction);
+    }
+
+    public void changedUpdate(DocumentEvent event, FoldHierarchyTransaction transaction) {
+//        update(event.getDocument(), transaction);
+    }
+
+    public void removeEmptyNotify(Fold arg0) {
+    }
+
+    public void removeDamagedNotify(Fold arg0) {
+    }
+
+    public void expandNotify(Fold arg0) {
+    }
+
+    public void release() {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/TextEditor/src/com/sun/hotspot/igv/texteditor/TextFoldManagerFactory.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.texteditor;
+
+import org.netbeans.spi.editor.fold.FoldManager;
+import org.netbeans.spi.editor.fold.FoldManagerFactory;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class TextFoldManagerFactory implements FoldManagerFactory{
+    public FoldManager createFoldManager() {
+        return new TextFoldManager();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/TextEditor/src/com/sun/hotspot/igv/texteditor/TextHighlightsLayerFactory.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.texteditor;
+
+import org.netbeans.spi.editor.highlighting.HighlightsLayer;
+import org.netbeans.spi.editor.highlighting.HighlightsLayerFactory;
+import org.netbeans.spi.editor.highlighting.ZOrder;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class TextHighlightsLayerFactory implements HighlightsLayerFactory {
+    public HighlightsLayer[] createLayers(HighlightsLayerFactory.Context context) {
+        return new HighlightsLayer[] {
+            HighlightsLayer.create("com.sun.hotspot.igv.texteditor.SyntaxLayer", ZOrder.TOP_RACK, true, new SyntaxLayer(context))
+        };
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/TextEditor/src/com/sun/hotspot/igv/texteditor/TextSideBarFactory.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.texteditor;
+
+import javax.swing.JComponent;
+import javax.swing.text.JTextComponent;
+import org.netbeans.editor.CodeFoldingSideBar;
+import org.netbeans.editor.SideBarFactory;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class TextSideBarFactory implements SideBarFactory {
+    public JComponent createSideBar(JTextComponent text) {
+        return new CodeFoldingSideBar(text);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/TextEditor/src/com/sun/hotspot/igv/texteditor/layer.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd">
+<filesystem>
+    
+    <folder name="Editors">
+        <folder name="Preferences"/>
+        <folder name="text">
+            <folder name="text-igv">
+                <file name="EditorKit.instance">
+                <attr name="instanceClass" stringvalue="com.sun.hotspot.igv.texteditor.TextEditorKit"/>
+                </file>
+                <folder name="FoldManager">
+                    <file name="com-sun-hotspot-igv-texteditor-TextFoldManagerFactory.instance"/>
+                </folder>
+                <folder name="Preferences">
+                    <file name="org-netbeans-modules-editor-preferences.xml" url="org-netbeans-modules-editor-preferences.xml"/>
+                </folder>
+                <folder name="SideBar">
+                    <file name="com-sun-hotspot-igv-texteditor-TextSideBarFactory.instance">
+                        <attr name="position" intvalue="1500"/>
+                    </file>
+                </folder>
+                <file name="com-sun-hotspot-igv-texteditor-TextHighlightsLayerFactory.instance"/>
+                </folder>
+        </folder>
+    </folder>
+</filesystem>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/TextEditor/src/com/sun/hotspot/igv/texteditor/org-netbeans-modules-editor-preferences.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,51 @@
+<?xml version="1.0"?>
+<!--
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
+
+
+The contents of this file are subject to the terms of either the GNU
+General Public License Version 2 only ("GPL") or the Common
+Development and Distribution License("CDDL") (collectively, the
+"License"). You may not use this file except in compliance with the
+License. You can obtain a copy of the License at
+http://www.netbeans.org/cddl-gplv2.html
+or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+specific language governing permissions and limitations under the
+License.  When distributing the software, include this License Header
+Notice in each file and include the License file at
+nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
+particular file as subject to the "Classpath" exception as provided
+by Sun in the GPL Version 2 section of the License file that
+accompanied this code. If applicable, add the following below the
+License Header, with the fields enclosed by brackets [] replaced by
+your own identifying information:
+"Portions Copyrighted [year] [name of copyright owner]"
+
+Contributor(s):
+
+The Original Software is NetBeans. The Initial Developer of the Original
+Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
+Microsystems, Inc. All Rights Reserved.
+
+If you wish your version of this file to be governed by only the CDDL
+or only the GPL Version 2, indicate your decision by adding
+"[Contributor] elects to include this software in this distribution
+under the [CDDL or GPL Version 2] license." If you do not indicate a
+single choice of license, a recipient has the option to distribute
+your version of this file under either the CDDL, the GPL Version 2 or
+to extend the choice of license to its licensees as provided above.
+However, if you add GPL Version 2 code and therefore, elected the GPL
+Version 2 license, then the option applies only if the new code is
+made subject to such option by the copyright holder.
+-->
+<!DOCTYPE editor-preferences PUBLIC "-//NetBeans//DTD Editor Preferences 1.0//EN" "http://www.netbeans.org/dtds/EditorPreferences-1_0.dtd">
+
+<editor-preferences>
+    <entry name="toolbarVisible" value="false" javaType="java.lang.Boolean" />
+    <entry name="line-number-visible" value="false" javaType="java.lang.Boolean" />
+    <entry name="code-folding-enable" value="true" javaType="java.lang.Boolean" />
+    <entry name="status-bar-visible" value="false" javaType="java.lang.Boolean" />
+    <entry name="text-limit-line-visible" value="false" javaType="java.lang.Boolean" />
+</editor-preferences>
--- a/src/share/tools/IdealGraphVisualizer/Util/nbproject/project.xml	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Util/nbproject/project.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -19,7 +19,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>2.9</specification-version>
+                        <specification-version>2.27.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -27,7 +27,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.2.1.1</specification-version>
+                        <specification-version>7.20.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -35,7 +35,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.10.1.1</specification-version>
+                        <specification-version>8.14.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.lookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.6.1</specification-version>
                     </run-dependency>
                 </dependency>
             </module-dependencies>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/LookupHistory.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,78 @@
+/*
+ * 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.sun.hotspot.igv.util;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.openide.util.Lookup.Result;
+import org.openide.util.LookupEvent;
+import org.openide.util.LookupListener;
+import org.openide.util.Utilities;
+
+/**
+ *
+ * @author Thomas
+ */
+public class LookupHistory {
+
+    private static Map<Class, LookupHistoryImpl> cache = new HashMap<Class, LookupHistoryImpl>();
+
+    private static class LookupHistoryImpl<T> implements LookupListener {
+
+        private Class<T> klass;
+        private Result<T> result;
+        private T last;
+
+        public LookupHistoryImpl(Class<T> klass) {
+            this.klass = klass;
+            result = Utilities.actionsGlobalContext().lookupResult(klass);
+            result.addLookupListener(this);
+            last = Utilities.actionsGlobalContext().lookup(klass);
+        }
+
+        public T getLast() {
+            return last;
+        }
+
+        public void resultChanged(LookupEvent ev) {
+            T current = Utilities.actionsGlobalContext().lookup(klass);
+            if (current != null) {
+                last = current;
+            }
+        }
+    }
+
+    public static <T> void init(Class<T> klass) {
+        if (!cache.containsKey(klass)) {
+            cache.put(klass, new LookupHistoryImpl<T>(klass));
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> T getLast(Class<T> klass) {
+        init(klass);
+        assert cache.containsKey(klass);
+        return (T) cache.get(klass).getLast();
+    }
+}
--- a/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/RangeSliderModel.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/RangeSliderModel.java	Wed Jul 27 17:32:44 2011 -0700
@@ -69,16 +69,17 @@
         this.colorChangedEvent = new ChangedEvent<RangeSliderModel>(this);
         setPositions(positions);
     }
-
+    
     protected void setPositions(List<String> positions) {
         this.positions = positions;
-        colors = new ArrayList<Color>();
-        for (int i = 0; i < positions.size(); i++) {
-            colors.add(Color.black);
-        }
+         colors = new ArrayList<Color>();
+         for (int i = 0; i < positions.size(); i++) {
+             colors.add(Color.black);
+         }
         changedEvent.fire();
         colorChangedEvent.fire();
-    }
+     }
+
 
     public void setColors(List<Color> colors) {
         this.colors = colors;
--- a/src/share/tools/IdealGraphVisualizer/View/nbproject/project.xml	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/View/nbproject/project.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -55,6 +55,14 @@
                     </run-dependency>
                 </dependency>
                 <dependency>
+                    <code-name-base>com.sun.hotspot.igv.selectioncoordinator</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
                     <code-name-base>com.sun.hotspot.igv.settings</code-name-base>
                     <build-prerequisite/>
                     <compile-dependency/>
@@ -83,7 +91,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>2.9</specification-version>
+                        <specification-version>2.27.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.spi.quicksearch</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -91,7 +107,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.6.0.1</specification-version>
+                        <specification-version>6.21.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -99,7 +115,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.11.0.1</specification-version>
+                        <specification-version>7.30.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -107,7 +123,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.5.1</specification-version>
+                        <specification-version>7.18.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -115,7 +131,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.7</specification-version>
+                        <specification-version>7.20.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -123,7 +139,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.2.1.1</specification-version>
+                        <specification-version>7.20.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -131,7 +147,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.9.0.1</specification-version>
+                        <specification-version>8.14.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.lookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.6.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -139,7 +163,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.16</specification-version>
+                        <specification-version>6.39.1</specification-version>
                     </run-dependency>
                 </dependency>
             </module-dependencies>
--- a/src/share/tools/IdealGraphVisualizer/View/src/META-INF/services/com.sun.hotspot.igv.data.services.InputGraphProvider	Tue Jun 28 10:57:38 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-com.sun.hotspot.igv.view.EditorInputGraphProvider
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/Bundle.properties	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/Bundle.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -1,3 +1,4 @@
-HINT_EditorTopComponent=This is a Editor window
-OpenIDE-Module-Name=View
-CTL_EditorTopComponent=Editor Window
+HINT_EditorTopComponent=Visualizes a graph.
+OpenIDE-Module-Name=View
+CTL_EditorTopComponent=Graph
+QuickSearch/Nodes/com-sun-hotspot-igv-view-NodeQuickSearch.instance=Nodes
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/ConnectionAnchor.java	Tue Jun 28 10:57:38 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-package com.sun.hotspot.igv.view;
-
-import com.sun.hotspot.igv.view.widgets.SlotWidget;
-import java.awt.Point;
-import java.awt.Rectangle;
-import org.netbeans.api.visual.anchor.Anchor;
-import org.netbeans.api.visual.anchor.Anchor.Entry;
-import org.netbeans.api.visual.anchor.Anchor.Result;
-import org.netbeans.api.visual.widget.Widget;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public class ConnectionAnchor extends Anchor {
-
-    public enum HorizontalAlignment {
-
-        Left,
-        Center,
-        Right
-    }
-    private HorizontalAlignment alignment;
-
-    public ConnectionAnchor(Widget widget) {
-        this(HorizontalAlignment.Center, widget);
-    }
-
-    public ConnectionAnchor(HorizontalAlignment alignment, Widget widget) {
-        super(widget);
-        this.alignment = alignment;
-    }
-
-    public Result compute(Entry entry) {
-        return new Result(getRelatedSceneLocation(), Anchor.DIRECTION_ANY);
-    }
-
-    @Override
-    public Point getRelatedSceneLocation() {
-        Point p = null;
-        Widget w = getRelatedWidget();
-        if (w != null) {
-            if (w instanceof SlotWidget) {
-                p = ((SlotWidget) w).getAnchorPosition();
-            } else {
-                Rectangle r = w.convertLocalToScene(w.getBounds());
-                int y = r.y + r.height / 2;
-                int x = r.x;
-                if (alignment == HorizontalAlignment.Center) {
-                    x = r.x + r.width / 2;
-                } else if (alignment == HorizontalAlignment.Right) {
-                    x = r.x + r.width;
-                }
-
-                p = new Point(x, y);
-            }
-        }
-
-        return p;
-    }
-}
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramScene.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramScene.java	Wed Jul 27 17:32:44 2011 -0700
@@ -31,39 +31,40 @@
 import com.sun.hotspot.igv.graph.Connection;
 import com.sun.hotspot.igv.graph.Diagram;
 import com.sun.hotspot.igv.graph.Figure;
-import com.sun.hotspot.igv.graph.InputSlot;
 import com.sun.hotspot.igv.graph.OutputSlot;
-import com.sun.hotspot.igv.graph.Slot;
 import com.sun.hotspot.igv.hierarchicallayout.HierarchicalClusterLayoutManager;
 import com.sun.hotspot.igv.hierarchicallayout.OldHierarchicalLayoutManager;
 import com.sun.hotspot.igv.hierarchicallayout.HierarchicalLayoutManager;
 import com.sun.hotspot.igv.view.widgets.FigureWidget;
+import com.sun.hotspot.igv.layout.LayoutGraph;
+import com.sun.hotspot.igv.data.services.Scheduler;
+import com.sun.hotspot.igv.data.ChangedListener;
+import com.sun.hotspot.igv.data.ControllableChangedListener;
+import com.sun.hotspot.igv.data.Pair;
+import com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.graph.Block;
+import com.sun.hotspot.igv.graph.InputSlot;
+import com.sun.hotspot.igv.graph.Slot;
+import com.sun.hotspot.igv.selectioncoordinator.SelectionCoordinator;
+import com.sun.hotspot.igv.util.ColorIcon;
+import com.sun.hotspot.igv.util.PropertiesSheet;
 import com.sun.hotspot.igv.view.widgets.InputSlotWidget;
 import com.sun.hotspot.igv.view.widgets.OutputSlotWidget;
 import com.sun.hotspot.igv.view.widgets.SlotWidget;
-import com.sun.hotspot.igv.layout.LayoutGraph;
-import com.sun.hotspot.igv.data.services.Scheduler;
-import com.sun.hotspot.igv.data.ChangedListener;
-import com.sun.hotspot.igv.graph.Block;
-import com.sun.hotspot.igv.util.ColorIcon;
-import com.sun.hotspot.igv.util.ExtendedSelectAction;
 import java.awt.Color;
+import java.awt.Component;
 import java.awt.Dimension;
 import java.awt.Point;
 import java.awt.Rectangle;
 import java.awt.event.ActionEvent;
-import java.awt.event.FocusEvent;
-import java.awt.event.FocusListener;
-import java.awt.event.MouseEvent;
-import java.awt.event.MouseListener;
-import java.awt.event.MouseMotionListener;
 import java.awt.event.MouseWheelEvent;
 import java.awt.event.MouseWheelListener;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -74,8 +75,6 @@
 import javax.swing.JPopupMenu;
 import javax.swing.JScrollPane;
 import javax.swing.SwingUtilities;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
 import javax.swing.event.UndoableEditEvent;
 import javax.swing.undo.AbstractUndoableEdit;
 import javax.swing.undo.CannotRedoException;
@@ -84,16 +83,20 @@
 import org.netbeans.api.visual.action.PopupMenuProvider;
 import org.netbeans.api.visual.action.RectangularSelectDecorator;
 import org.netbeans.api.visual.action.RectangularSelectProvider;
-import org.netbeans.api.visual.action.SelectProvider;
 import org.netbeans.api.visual.action.WidgetAction;
 import org.netbeans.api.visual.animator.SceneAnimator;
 import org.netbeans.api.visual.layout.LayoutFactory;
-import org.netbeans.api.visual.widget.ConnectionWidget;
+import org.netbeans.api.visual.model.ObjectScene;
+import org.netbeans.api.visual.model.ObjectSceneEvent;
+import org.netbeans.api.visual.model.ObjectSceneEventType;
+import org.netbeans.api.visual.model.ObjectSceneListener;
+import org.netbeans.api.visual.model.ObjectState;
 import org.netbeans.api.visual.widget.LayerWidget;
-import org.netbeans.api.visual.widget.Scene;
 import org.netbeans.api.visual.widget.Widget;
-import org.netbeans.api.visual.widget.LabelWidget;
 import org.openide.awt.UndoRedo;
+import org.openide.nodes.AbstractNode;
+import org.openide.nodes.Children;
+import org.openide.nodes.Sheet;
 import org.openide.util.Lookup;
 import org.openide.util.lookup.AbstractLookup;
 import org.openide.util.lookup.InstanceContent;
@@ -102,15 +105,10 @@
  *
  * @author Thomas Wuerthinger
  */
-public class DiagramScene extends Scene implements ChangedListener<DiagramViewModel> {
+public class DiagramScene extends ObjectScene implements DiagramViewer {
 
-    private HashMap<Figure, FigureWidget> figureWidgets;
-    private HashMap<Slot, SlotWidget> slotWidgets;
-    private HashMap<Connection, ConnectionWidget> connectionWidgets;
-    private HashMap<InputBlock, BlockWidget> blockWidgets;
-    private Widget hoverWidget;
     private WidgetAction hoverAction;
-    private List<FigureWidget> selectedWidgets;
+    private WidgetAction selectAction;
     private Lookup lookup;
     private InstanceContent content;
     private Action[] actions;
@@ -118,22 +116,25 @@
     private JScrollPane scrollPane;
     private UndoRedo.Manager undoRedoManager;
     private LayerWidget mainLayer;
-    private LayerWidget slotLayer;
     private LayerWidget blockLayer;
-    private double realZoomFactor;
-    private BoundedZoomAction zoomAction;
-    private WidgetAction panAction;
     private Widget topLeft;
     private Widget bottomRight;
-    private LayerWidget startLayer;
-    private LabelWidget startLabel;
     private DiagramViewModel model;
     private DiagramViewModel modelCopy;
-    public static final int AFTER = 1;
-    public static final int BEFORE = 1;
+    private WidgetAction zoomAction;
+    private boolean rebuilding;
+    
+    /**
+     * The alpha level of partially visible figures.
+     */
     public static final float ALPHA = 0.4f;
-    public static final int GRID_SIZE = 30;
+    
+    /**
+     * The offset of the graph to the border of the window showing it.
+     */
     public static final int BORDER_SIZE = 20;
+    
+    
     public static final int UNDOREDO_LIMIT = 100;
     public static final int SCROLL_UNIT_INCREMENT = 80;
     public static final int SCROLL_BLOCK_INCREMENT = 400;
@@ -142,6 +143,7 @@
     public static final float ZOOM_INCREMENT = 1.5f;
     public static final int SLOT_OFFSET = 6;
     public static final int ANIMATION_LIMIT = 40;
+    
     private PopupMenuProvider popupMenuProvider = new PopupMenuProvider() {
 
         public JPopupMenu getPopupMenu(Widget widget, Point localLocation) {
@@ -157,6 +159,90 @@
             return widget;
         }
     };
+
+    @SuppressWarnings("unchecked")
+    public <T> T getWidget(Object o) {
+        Widget w = this.findWidget(o);
+        return (T) w;
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T> T getWidget(Object o, Class<T> klass) {
+        Widget w = this.findWidget(o);
+        return (T) w;
+    }
+
+    private static boolean intersects(Set<? extends Object> s1, Set<? extends Object> s2) {
+        for (Object o : s1) {
+            if (s2.contains(o)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void zoomOut() {
+        double zoom = getZoomFactor();
+        Point viewPosition = getScrollPane().getViewport().getViewPosition();
+        double newZoom = zoom / DiagramScene.ZOOM_INCREMENT;
+        if (newZoom > DiagramScene.ZOOM_MIN_FACTOR) {
+            setZoomFactor(newZoom);
+            validate();
+            getScrollPane().getViewport().setViewPosition(new Point((int) (viewPosition.x / DiagramScene.ZOOM_INCREMENT), (int) (viewPosition.y / DiagramScene.ZOOM_INCREMENT)));
+        }
+    }
+
+    public void zoomIn() {
+
+        double zoom = getZoomFactor();
+        Point viewPosition = getScrollPane().getViewport().getViewPosition();
+        double newZoom = zoom * DiagramScene.ZOOM_INCREMENT;
+        if (newZoom < DiagramScene.ZOOM_MAX_FACTOR) {
+            setZoomFactor(newZoom);
+            validate();
+            getScrollPane().getViewport().setViewPosition(new Point((int) (viewPosition.x * DiagramScene.ZOOM_INCREMENT), (int) (viewPosition.y * DiagramScene.ZOOM_INCREMENT)));
+        }
+    }
+
+
+    public void centerFigures(List<Figure> list) {
+
+        boolean b = getUndoRedoEnabled();
+        setUndoRedoEnabled(false);
+        gotoFigures(list);
+        setUndoRedoEnabled(b);
+    }
+
+    private Set<Object> getObjectsFromIdSet(Set<Object> set) {
+        Set<Object> selectedObjects = new HashSet<Object>();
+        for (Figure f : getModel().getDiagramToView().getFigures()) {
+            if (intersects(f.getSource().getSourceNodesAsSet(), set)) {
+                selectedObjects.add(f);
+            }
+
+            for (Slot s : f.getSlots()) {
+                if (intersects(s.getSource().getSourceNodesAsSet(), set)) {
+                    selectedObjects.add(s);
+                }
+            }
+        }
+        return selectedObjects;
+    }
+    private ControllableChangedListener<SelectionCoordinator> highlightedCoordinatorListener = new ControllableChangedListener<SelectionCoordinator>() {
+
+        public void filteredChanged(SelectionCoordinator source) {
+            DiagramScene.this.setHighlightedObjects(getObjectsFromIdSet(source.getHighlightedObjects()));
+            DiagramScene.this.validate();
+        }
+    };
+    private ControllableChangedListener<SelectionCoordinator> selectedCoordinatorListener = new ControllableChangedListener<SelectionCoordinator>() {
+
+        public void filteredChanged(SelectionCoordinator source) {
+            DiagramScene.this.gotoSelection(source.getSelectedObjects());
+            DiagramScene.this.validate();
+        }
+    };
+
     private RectangularSelectProvider rectangularSelectProvider = new RectangularSelectProvider() {
 
         public void performSelection(Rectangle rectangle) {
@@ -170,168 +256,41 @@
                 rectangle.height *= -1;
             }
 
-            boolean updated = false;
+            Set<Object> selectedObjects = new HashSet<Object>();
             for (Figure f : getModel().getDiagramToView().getFigures()) {
-                FigureWidget w = figureWidgets.get(f);
-                Rectangle r = new Rectangle(w.getBounds());
-                r.setLocation(w.getLocation());
-                if (r.intersects(rectangle)) {
-                    if (!selectedWidgets.contains(w)) {
-                        addToSelection(w);
-                        updated = true;
+                FigureWidget w = getWidget(f);
+                if (w != null) {
+                    Rectangle r = new Rectangle(w.getBounds());
+                    r.setLocation(w.getLocation());
+
+                    if (r.intersects(rectangle)) {
+                        selectedObjects.add(f);
+                    }
+
+                    for (Slot s : f.getSlots()) {
+                        SlotWidget sw = getWidget(s);
+                        Rectangle r2 = new Rectangle(sw.getBounds());
+                        r2.setLocation(sw.convertLocalToScene(new Point(0, 0)));
+
+                        if (r2.intersects(rectangle)) {
+                            selectedObjects.add(s);
+                        }
                     }
                 } else {
-                    if (selectedWidgets.contains(w)) {
-                        selectedWidgets.remove(w);
-                        content.remove(w.getNode());
-                        w.setState(w.getState().deriveSelected(false));
-                        updated = true;
-                    }
-                }
-            }
-
-            if (updated) {
-                selectionUpdated();
-            }
-        }
-    };
-    private SelectProvider selectProvider = new SelectProvider() {
-
-        public boolean isAimingAllowed(Widget widget, Point point, boolean b) {
-            return false;
-        }
-
-        public boolean isSelectionAllowed(Widget widget, Point point, boolean b) {
-            return widget instanceof FigureWidget || widget == DiagramScene.this;
-        }
-
-        public void select(Widget w, Point point, boolean change) {
-
-            boolean updated = false;
-
-            if (w == DiagramScene.this) {
-                if (DiagramScene.this.selectedWidgets.size() != 0) {
-                    clearSelection();
-                    selectionUpdated();
-                }
-                return;
-            }
-
-            FigureWidget widget = (FigureWidget) w;
-
-
-            if (change) {
-                if (widget.getState().isSelected()) {
-                    assert selectedWidgets.contains(widget);
-                    widget.setState(widget.getState().deriveSelected(false));
-                    selectedWidgets.remove(widget);
-                    content.remove(widget.getNode());
-                    updated = true;
-                } else {
-                    assert !selectedWidgets.contains(widget);
-                    addToSelection(widget);
-                    updated = true;
-                    assert widget.getState().isSelected();
-                }
-            } else {
-
-                if (widget.getState().isSelected()) {
-                    assert selectedWidgets.contains(widget);
-                } else {
-
-                    assert !selectedWidgets.contains(widget);
-                    clearSelection();
-                    addToSelection(widget);
-                    updated = true;
-                    assert widget.getState().isSelected();
+                    assert false : "w should not be null here!";
                 }
             }
 
-            if (updated) {
-                selectionUpdated();
-            }
-
+            setSelectedObjects(selectedObjects);
         }
     };
-
-    private FigureWidget getFigureWidget(Figure f) {
-        return figureWidgets.get(f);
-    }
-    private FocusListener focusListener = new FocusListener() {
-
-        public void focusGained(FocusEvent e) {
-            DiagramScene.this.getView().requestFocus();
-        }
-
-        public void focusLost(FocusEvent e) {
-        }
-    };
+    
     private MouseWheelListener mouseWheelListener = new MouseWheelListener() {
 
         public void mouseWheelMoved(MouseWheelEvent e) {
-            DiagramScene.this.zoomAction.mouseWheelMoved(DiagramScene.this, new WidgetAction.WidgetMouseWheelEvent(0, e));
-            DiagramScene.this.validate();
-        }
-    };
-    private MouseListener mouseListener = new MouseListener() {
-
-        public void mouseClicked(MouseEvent e) {
-            DiagramScene.this.panAction.mouseClicked(DiagramScene.this, new WidgetAction.WidgetMouseEvent(0, e));
-        }
-
-        public void mousePressed(MouseEvent e) {
-            DiagramScene.this.panAction.mousePressed(DiagramScene.this, new WidgetAction.WidgetMouseEvent(0, e));
-        }
-
-        public void mouseReleased(MouseEvent e) {
-            DiagramScene.this.panAction.mouseReleased(DiagramScene.this, new WidgetAction.WidgetMouseEvent(0, e));
-        }
-
-        public void mouseEntered(MouseEvent e) {
-            DiagramScene.this.panAction.mouseEntered(DiagramScene.this, new WidgetAction.WidgetMouseEvent(0, e));
-        }
-
-        public void mouseExited(MouseEvent e) {
-            DiagramScene.this.panAction.mouseExited(DiagramScene.this, new WidgetAction.WidgetMouseEvent(0, e));
+            DiagramScene.this.relayoutWithoutLayout(null);
         }
     };
-    private MouseMotionListener mouseMotionListener = new MouseMotionListener() {
-
-        public void mouseDragged(MouseEvent e) {
-            DiagramScene.this.panAction.mouseDragged(DiagramScene.this, new WidgetAction.WidgetMouseEvent(0, e));
-        }
-
-        public void mouseMoved(MouseEvent e) {
-        }
-    };
-    private ScrollChangeListener scrollChangeListener = new ScrollChangeListener();
-
-    private class ScrollChangeListener implements ChangeListener {
-
-        private Map<Widget, Point> relativePositions = new HashMap<Widget, Point>();
-        private Point oldPosition;
-
-        public void register(Widget w, Point p) {
-            relativePositions.put(w, p);
-        }
-
-        public void unregister(Widget w) {
-            relativePositions.remove(w);
-        }
-
-        public void stateChanged(ChangeEvent e) {
-            Point p = DiagramScene.this.getScrollPane().getViewport().getViewPosition();
-            if (oldPosition == null || !p.equals(oldPosition)) {
-                for (Widget w : relativePositions.keySet()) {
-                    Point curPoint = relativePositions.get(w);
-                    Point newPoint = new Point(p.x + curPoint.x, p.y + curPoint.y);
-                    w.setPreferredLocation(newPoint);
-                    DiagramScene.this.validate();
-                }
-                oldPosition = p;
-            }
-        }
-    }
 
     public Point getScrollPosition() {
         return getScrollPane().getViewport().getViewPosition();
@@ -341,43 +300,123 @@
         getScrollPane().getViewport().setViewPosition(p);
     }
 
-    public DiagramScene(Action[] actions, DiagramViewModel model) {
-        this.actions = actions;
-        selectedWidgets = new ArrayList<FigureWidget>();
-        content = new InstanceContent();
-        lookup = new AbstractLookup(content);
-        this.setCheckClipping(true);
-        this.getInputBindings().setZoomActionModifiers(0);
-
+    private JScrollPane createScrollPane() {
         JComponent comp = this.createView();
         comp.setDoubleBuffered(true);
         comp.setBackground(Color.WHITE);
         comp.setOpaque(true);
-
         this.setBackground(Color.WHITE);
         this.setOpaque(true);
-        scrollPane = new JScrollPane(comp);
-        scrollPane.setBackground(Color.WHITE);
-        scrollPane.getVerticalScrollBar().setUnitIncrement(SCROLL_UNIT_INCREMENT);
-        scrollPane.getVerticalScrollBar().setBlockIncrement(SCROLL_BLOCK_INCREMENT);
-        scrollPane.getHorizontalScrollBar().setUnitIncrement(SCROLL_UNIT_INCREMENT);
-        scrollPane.getHorizontalScrollBar().setBlockIncrement(SCROLL_BLOCK_INCREMENT);
-        scrollPane.getViewport().addChangeListener(scrollChangeListener);
-        hoverAction = this.createWidgetHoverAction();
+        JScrollPane result = new JScrollPane(comp);
+        result.setBackground(Color.WHITE);
+        result.getVerticalScrollBar().setUnitIncrement(SCROLL_UNIT_INCREMENT);
+        result.getVerticalScrollBar().setBlockIncrement(SCROLL_BLOCK_INCREMENT);
+        result.getHorizontalScrollBar().setUnitIncrement(SCROLL_UNIT_INCREMENT);
+        result.getHorizontalScrollBar().setBlockIncrement(SCROLL_BLOCK_INCREMENT);
+        return result;
+    }
+    private ObjectSceneListener selectionChangedListener = new ObjectSceneListener() {
+
+        public void objectAdded(ObjectSceneEvent arg0, Object arg1) {
+        }
+
+        public void objectRemoved(ObjectSceneEvent arg0, Object arg1) {
+        }
+
+        public void objectStateChanged(ObjectSceneEvent e, Object o, ObjectState oldState, ObjectState newState) {
+        }
+
+        public void selectionChanged(ObjectSceneEvent e, Set<Object> oldSet, Set<Object> newSet) {
+            DiagramScene scene = (DiagramScene) e.getObjectScene();
+            if (scene.isRebuilding()) {
+                return;
+            }
+
+            content.set(newSet, null);
+
+            Set<Integer> nodeSelection = new HashSet<Integer>();
+            for (Object o : newSet) {
+                if (o instanceof Properties.Provider) {
+                    final Properties.Provider provider = (Properties.Provider) o;
+                    AbstractNode node = new AbstractNode(Children.LEAF) {
+
+                        @Override
+                        protected Sheet createSheet() {
+                            Sheet s = super.createSheet();
+                            PropertiesSheet.initializeSheet(provider.getProperties(), s);
+                            return s;
+                        }
+                    };
+                    node.setDisplayName(provider.getProperties().get("name"));
+                    content.add(node);
+                }
+
+
+                if (o instanceof Figure) {
+                    nodeSelection.addAll(((Figure) o).getSource().getSourceNodesAsSet());
+                } else if (o instanceof Slot) {
+                    nodeSelection.addAll(((Slot) o).getSource().getSourceNodesAsSet());
+                }
+            }
+            getModel().setSelectedNodes(nodeSelection);
+
+            boolean b = selectedCoordinatorListener.isEnabled();
+            selectedCoordinatorListener.setEnabled(false);
+            SelectionCoordinator.getInstance().setSelectedObjects(nodeSelection);
+            selectedCoordinatorListener.setEnabled(b);
+
+        }
+
+        public void highlightingChanged(ObjectSceneEvent e, Set<Object> oldSet, Set<Object> newSet) {
+            Set<Integer> nodeHighlighting = new HashSet<Integer>();
+            for (Object o : newSet) {
+                if (o instanceof Figure) {
+                    nodeHighlighting.addAll(((Figure) o).getSource().getSourceNodesAsSet());
+                } else if (o instanceof Slot) {
+                    nodeHighlighting.addAll(((Slot) o).getSource().getSourceNodesAsSet());
+                }
+            }
+            boolean b = highlightedCoordinatorListener.isEnabled();
+            highlightedCoordinatorListener.setEnabled(false);
+            SelectionCoordinator.getInstance().setHighlightedObjects(nodeHighlighting);
+            highlightedCoordinatorListener.setEnabled(true);
+        }
+
+        public void hoverChanged(ObjectSceneEvent e, Object oldObject, Object newObject) {
+            Set<Object> newHighlightedObjects = new HashSet<Object>(DiagramScene.this.getHighlightedObjects());
+            if (oldObject != null) {
+                newHighlightedObjects.remove(oldObject);
+            }
+            if (newObject != null) {
+                newHighlightedObjects.add(newObject);
+            }
+            DiagramScene.this.setHighlightedObjects(newHighlightedObjects);
+        }
+
+        public void focusChanged(ObjectSceneEvent arg0, Object arg1, Object arg2) {
+        }
+    };
+
+    public DiagramScene(Action[] actions, DiagramViewModel model) {
+
+        this.actions = actions;
+
+        content = new InstanceContent();
+        lookup = new AbstractLookup(content);
+
+        this.setCheckClipping(true);
+
+        this.getInputBindings().setZoomActionModifiers(0);
+
+        scrollPane = createScrollPane();
+        this.getActions().addAction(ActionFactory.createPanAction());
+        hoverAction = createObjectHoverAction();
+        selectAction = createSelectAction();
+        this.getActions().addAction(selectAction);
 
         blockLayer = new LayerWidget(this);
         this.addChild(blockLayer);
 
-        startLayer = new LayerWidget(this);
-        this.addChild(startLayer);
-        // TODO: String startLabelString = "Loading graph with " + originalDiagram.getFigures().size() + " figures and " + originalDiagram.getConnections().size() + " connections...";
-        String startLabelString = "";
-        LabelWidget w = new LabelWidget(this, startLabelString);
-        scrollChangeListener.register(w, new Point(10, 10));
-        w.setAlignment(LabelWidget.Alignment.CENTER);
-        startLabel = w;
-        startLayer.addChild(w);
-
         mainLayer = new LayerWidget(this);
         this.addChild(mainLayer);
 
@@ -385,14 +424,10 @@
         topLeft.setPreferredLocation(new Point(-BORDER_SIZE, -BORDER_SIZE));
         this.addChild(topLeft);
 
-
         bottomRight = new Widget(this);
         bottomRight.setPreferredLocation(new Point(-BORDER_SIZE, -BORDER_SIZE));
         this.addChild(bottomRight);
 
-        slotLayer = new LayerWidget(this);
-        this.addChild(slotLayer);
-
         connectionLayer = new LayerWidget(this);
         this.addChild(connectionLayer);
 
@@ -401,52 +436,34 @@
 
         this.setLayout(LayoutFactory.createAbsoluteLayout());
 
-        this.getActions().addAction(hoverAction);
-        zoomAction = new BoundedZoomAction(1.1, false);
-        zoomAction.setMaxFactor(ZOOM_MAX_FACTOR);
-        zoomAction.setMinFactor(ZOOM_MIN_FACTOR);
-        this.getActions().addAction(ActionFactory.createMouseCenteredZoomAction(1.1));
-        panAction = new ExtendedPanAction();
-        this.getActions().addAction(panAction);
+        zoomAction = ActionFactory.createMouseCenteredZoomAction(1.2);
+        this.getActions().addAction(zoomAction);
+        this.getView().addMouseWheelListener(mouseWheelListener);
         this.getActions().addAction(ActionFactory.createPopupMenuAction(popupMenuProvider));
 
         LayerWidget selectLayer = new LayerWidget(this);
         this.addChild(selectLayer);
         this.getActions().addAction(ActionFactory.createRectangularSelectAction(rectangularSelectDecorator, selectLayer, rectangularSelectProvider));
 
-        blockWidgets = new HashMap<InputBlock, BlockWidget>();
-
         boolean b = this.getUndoRedoEnabled();
         this.setUndoRedoEnabled(false);
         this.setNewModel(model);
         this.setUndoRedoEnabled(b);
-    }
-
-    private void selectionUpdated() {
-        getModel().setSelectedNodes(this.getSelectedNodes());
-        addUndo();
+        this.addObjectSceneListener(selectionChangedListener, ObjectSceneEventType.OBJECT_SELECTION_CHANGED, ObjectSceneEventType.OBJECT_HIGHLIGHTING_CHANGED, ObjectSceneEventType.OBJECT_HOVER_CHANGED);
     }
 
     public DiagramViewModel getModel() {
         return model;
     }
 
-    public void setRealZoomFactor(double d) {
-        this.realZoomFactor = d;
-    }
-
-    public double getRealZoomFactor() {
-        if (realZoomFactor == 0.0) {
-            return getZoomFactor();
-        } else {
-            return realZoomFactor;
-        }
-    }
-
     public JScrollPane getScrollPane() {
         return scrollPane;
     }
 
+    public Component getComponent() {
+        return scrollPane;
+    }
+    
     public boolean isAllVisible() {
         return getModel().getHiddenNodes().size() == 0;
     }
@@ -469,7 +486,7 @@
         if (f.getCluster() != null) {
             name += "B" + f.getCluster().toString();
         }
-        if (!this.getFigureWidget(f).isVisible()) {
+        if (!this.getWidget(f, FigureWidget.class).isVisible()) {
             if (f.getCluster() != null) {
                 name += ", ";
             }
@@ -481,100 +498,60 @@
     }
 
     public void setNewModel(DiagramViewModel model) {
-        if (this.model != null) {
-            this.model.getDiagramChangedEvent().removeListener(this);
-            this.model.getViewPropertiesChangedEvent().removeListener(this);
-        }
+        assert this.model == null : "can set model only once!";
         this.model = model;
+        this.modelCopy = null;
 
-        if (this.model == null) {
-            this.modelCopy = null;
-        } else {
-            this.modelCopy = this.model.copy();
-        }
-
-        model.getDiagramChangedEvent().addListener(this);
-        model.getViewPropertiesChangedEvent().addListener(this);
-
+        model.getDiagramChangedEvent().addListener(fullChange);
+        model.getViewPropertiesChangedEvent().addListener(fullChange);
+        model.getViewChangedEvent().addListener(selectionChange);
+        model.getHiddenNodesChangedEvent().addListener(hiddenNodesChange);
         update();
     }
 
     private void update() {
-
-        /*if (startLabel != null) {
-        // Animate fade-out
-        final LabelWidget labelWidget = this.startLabel;
-        labelWidget.setVisible(true);
-        RequestProcessor.getDefault().post(new Runnable() {
-        public void run() {
-        final int Sleep = 200;
-        final int Progress = 10;
-        for (int i = 0; i < 255 / Progress + 1; i++) {
-        try {
-        SwingUtilities.invokeAndWait(new Runnable() {
-        public void run() {
-        Color c = labelWidget.getForeground();
-        int v = c.getRed();
-        v += Progress;
-        if (v > 255) {
-        v = 255;
-        }
-        labelWidget.setForeground(new Color(v, v, v, 255 - v));
-        labelWidget.getScene().validate();
-        }
-        });
-        } catch (InterruptedException ex) {
-        } catch (InvocationTargetException ex) {
-        }
-        try {
-        Thread.sleep(Sleep);
-        } catch (InterruptedException ex) {
-        }
-        }
-        labelWidget.setVisible(false);
-        DiagramScene.this.scrollChangeListener.unregister(labelWidget);
-        }
-        }, 1000);
-        startLabel = null;
-        }*/
-
-        slotLayer.removeChildren();
         mainLayer.removeChildren();
         blockLayer.removeChildren();
+        
+        rebuilding = true;
 
-        blockWidgets.clear();
-        figureWidgets = new HashMap<Figure, FigureWidget>();
-        slotWidgets = new HashMap<Slot, SlotWidget>();
-        connectionWidgets = new HashMap<Connection, ConnectionWidget>();
+        Collection<Object> objects = new ArrayList<Object>(this.getObjects());
+        for (Object o : objects) {
+            this.removeObject(o);
+        }
 
-        WidgetAction selectAction = new ExtendedSelectAction(selectProvider);
         Diagram d = getModel().getDiagramToView();
 
-        if (getModel().getShowBlocks()) {
+        if (d.getGraph().getBlocks().isEmpty()) {
             Scheduler s = Lookup.getDefault().lookup(Scheduler.class);
-            Collection<InputBlock> newBlocks = new ArrayList<InputBlock>(s.schedule(d.getGraph()));
-            d.schedule(newBlocks);
+            d.getGraph().clearBlocks();
+            s.schedule(d.getGraph());
+            d.getGraph().ensureNodesInBlocks();
+            d.updateBlocks();
         }
 
         for (Figure f : d.getFigures()) {
-            FigureWidget w = new FigureWidget(f, this, mainLayer);
+            FigureWidget w = new FigureWidget(f, hoverAction, selectAction, this, mainLayer);
+            w.getActions().addAction(ActionFactory.createPopupMenuAction(w));
             w.getActions().addAction(selectAction);
             w.getActions().addAction(hoverAction);
-            w.getActions().addAction(ActionFactory.createPopupMenuAction(w));
-            w.getActions().addAction(new DoubleClickAction(w));
             w.setVisible(false);
 
-            figureWidgets.put(f, w);
+            this.addObject(f, w);
 
             for (InputSlot s : f.getInputSlots()) {
-                SlotWidget sw = new InputSlotWidget(s, this, slotLayer, w);
-                slotWidgets.put(s, sw);
+                SlotWidget sw = new InputSlotWidget(s, this, w, w);
+                addObject(s, sw);
+                sw.getActions().addAction(new DoubleClickAction(sw));
+                sw.getActions().addAction(hoverAction);
                 sw.getActions().addAction(selectAction);
             }
 
             for (OutputSlot s : f.getOutputSlots()) {
-                SlotWidget sw = new OutputSlotWidget(s, this, slotLayer, w);
-                slotWidgets.put(s, sw);
+                SlotWidget sw = new OutputSlotWidget(s, this, w, w);
+                addObject(s, sw);
+                sw.getActions().addAction(new DoubleClickAction(sw));
+                sw.getActions().addAction(hoverAction);
                 sw.getActions().addAction(selectAction);
             }
         }
@@ -583,28 +560,32 @@
             for (InputBlock bn : d.getGraph().getBlocks()) {
                 BlockWidget w = new BlockWidget(this, d, bn);
                 w.setVisible(false);
-                blockWidgets.put(bn, w);
+                this.addObject(bn, w);
                 blockLayer.addChild(w);
             }
         }
-
+        
+        rebuilding = false;
         this.smallUpdate(true);
-
+    }
+    
+    public boolean isRebuilding() {
+        return rebuilding;
     }
 
     private void smallUpdate(boolean relayout) {
 
+        System.out.println("smallUpdate " + relayout);
         this.updateHiddenNodes(model.getHiddenNodes(), relayout);
         boolean b = this.getUndoRedoEnabled();
         this.setUndoRedoEnabled(false);
-        this.setSelection(getModel().getSelectedNodes());
         this.setUndoRedoEnabled(b);
         this.validate();
     }
 
     private boolean isVisible(Connection c) {
-        FigureWidget w1 = figureWidgets.get(c.getInputSlot().getFigure());
-        FigureWidget w2 = figureWidgets.get(c.getOutputSlot().getFigure());
+        FigureWidget w1 = getWidget(c.getInputSlot().getFigure());
+        FigureWidget w2 = getWidget(c.getOutputSlot().getFigure());
 
         if (w1.isVisible() && w2.isVisible()) {
             return true;
@@ -614,13 +595,14 @@
     }
 
     private void relayout(Set<Widget> oldVisibleWidgets) {
+        System.out.println("relayout called with old visible widgets: " + oldVisibleWidgets);
 
         Diagram diagram = getModel().getDiagramToView();
 
         HashSet<Figure> figures = new HashSet<Figure>();
 
         for (Figure f : diagram.getFigures()) {
-            FigureWidget w = figureWidgets.get(f);
+            FigureWidget w = getWidget(f);
             if (w.isVisible()) {
                 figures.add(f);
             }
@@ -649,10 +631,20 @@
             manager.doLayout(new LayoutGraph(edges, figures));
         }
 
+        relayoutWithoutLayout(oldVisibleWidgets);
+    }
+    private Set<Pair<Point, Point>> lineCache = new HashSet<Pair<Point, Point>>();
+
+    private void relayoutWithoutLayout(Set<Widget> oldVisibleWidgets) {
+
+        System.out.println("relayout without layout with visible widgets: " + oldVisibleWidgets);
+
+        Diagram diagram = getModel().getDiagramToView();
+
         int maxX = -BORDER_SIZE;
         int maxY = -BORDER_SIZE;
         for (Figure f : diagram.getFigures()) {
-            FigureWidget w = figureWidgets.get(f);
+            FigureWidget w = getWidget(f);
             if (w.isVisible()) {
                 Point p = f.getPosition();
                 Dimension d = f.getSize();
@@ -663,8 +655,8 @@
 
         for (Connection c : diagram.getConnections()) {
             List<Point> points = c.getControlPoints();
-            FigureWidget w1 = figureWidgets.get((Figure) c.getTo().getVertex());
-            FigureWidget w2 = figureWidgets.get((Figure) c.getFrom().getVertex());
+            FigureWidget w1 = getWidget((Figure) c.getTo().getVertex());
+            FigureWidget w2 = getWidget((Figure) c.getFrom().getVertex());
             if (w1.isVisible() && w2.isVisible()) {
                 for (Point p : points) {
                     if (p != null) {
@@ -677,7 +669,7 @@
 
         if (getModel().getShowBlocks()) {
             for (Block b : diagram.getBlocks()) {
-                BlockWidget w = blockWidgets.get(b.getInputBlock());
+                BlockWidget w = getWidget(b.getInputBlock());
                 if (w != null && w.isVisible()) {
                     Rectangle r = b.getBounds();
                     maxX = Math.max(maxX, r.x + r.width);
@@ -693,6 +685,8 @@
         int curHeight = maxY + 2 * BORDER_SIZE;
 
         Rectangle bounds = this.getScrollPane().getBounds();
+        bounds.width /= getZoomFactor();
+        bounds.height /= getZoomFactor();
         if (curWidth < bounds.width) {
             offx = (bounds.width - curWidth) / 2;
         }
@@ -708,62 +702,61 @@
         connectionLayer.removeChildren();
         int visibleFigureCount = 0;
         for (Figure f : diagram.getFigures()) {
-            if (figureWidgets.get(f).isVisible()) {
+            if (getWidget(f, FigureWidget.class).isVisible()) {
                 visibleFigureCount++;
             }
         }
 
+
+        Set<Pair<Point, Point>> lastLineCache = lineCache;
+        lineCache = new HashSet<Pair<Point, Point>>();
+        for (Figure f : diagram.getFigures()) {
+            for (OutputSlot s : f.getOutputSlots()) {
+                SceneAnimator anim = animator;
+                if (visibleFigureCount > ANIMATION_LIMIT || oldVisibleWidgets == null) {
+                    anim = null;
+                }
+                processOutputSlot(lastLineCache, s, s.getConnections(), 0, null, null, offx2, offy2, anim);
+            }
+        }
+
         for (Figure f : diagram.getFigures()) {
-            for (OutputSlot s : f.getOutputSlots()) {
-                SceneAnimator anim = animator;
-                if (visibleFigureCount > ANIMATION_LIMIT) {
-                    anim = null;
-                }
-                processOutputSlot(s, s.getConnections(), 0, null, null, offx2, offy2, anim);
-            }
-        }
-
-        for (Figure f : diagram.getFigures()) {
-            FigureWidget w = figureWidgets.get(f);
+            FigureWidget w = getWidget(f);
             if (w.isVisible()) {
                 Point p = f.getPosition();
                 Point p2 = new Point(p.x + offx2, p.y + offy2);
-                Rectangle r = new Rectangle(p.x + offx2, p.y + offy2, f.getSize().width, f.getSize().height);
-                if (oldVisibleWidgets.contains(w)) {
-                    if (visibleFigureCount > ANIMATION_LIMIT) {
-                        w.setPreferredLocation(p2);
-                    } else {
-                        animator.animatePreferredLocation(w, p2);
-                    }
+                if ((visibleFigureCount <= ANIMATION_LIMIT && oldVisibleWidgets != null && oldVisibleWidgets.contains(w))) {
+                    animator.animatePreferredLocation(w, p2);
                 } else {
                     w.setPreferredLocation(p2);
+                    animator.animatePreferredLocation(w, p2);
                 }
             }
         }
 
         if (getModel().getShowBlocks()) {
             for (Block b : diagram.getBlocks()) {
-                BlockWidget w = blockWidgets.get(b.getInputBlock());
+                BlockWidget w = getWidget(b.getInputBlock());
                 if (w != null && w.isVisible()) {
                     Point location = new Point(b.getBounds().x + offx2, b.getBounds().y + offy2);
                     Rectangle r = new Rectangle(location.x, location.y, b.getBounds().width, b.getBounds().height);
-                    if (oldVisibleWidgets.contains(w)) {
-                        if (visibleFigureCount > ANIMATION_LIMIT) {
-                            w.setPreferredBounds(r);
-                        } else {
-                            animator.animatePreferredBounds(w, r);
-                        }
+                    
+                    if ((visibleFigureCount <= ANIMATION_LIMIT && oldVisibleWidgets != null && oldVisibleWidgets.contains(w))) {
+                        animator.animatePreferredBounds(w, r);
                     } else {
                         w.setPreferredBounds(r);
+                        animator.animatePreferredBounds(w, r);
                     }
                 }
             }
         }
+
+        this.validate();
     }
     private final Point specialNullPoint = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE);
 
-    private void processOutputSlot(OutputSlot s, List<Connection> connections, int controlPointIndex, Point lastPoint, LineWidget predecessor, int offx, int offy, SceneAnimator animator) {
-        Map<Point, List<Connection>> pointMap = new HashMap<Point, List<Connection>>();
+    private void processOutputSlot(Set<Pair<Point, Point>> lastLineCache, OutputSlot s, List<Connection> connections, int controlPointIndex, Point lastPoint, LineWidget predecessor, int offx, int offy, SceneAnimator animator) {
+        Map<Point, List<Connection>> pointMap = new HashMap<Point, List<Connection>>(connections.size());
 
         for (Connection c : connections) {
 
@@ -779,9 +772,9 @@
             Point cur = controlPoints.get(controlPointIndex);
             if (cur == null) {
                 cur = specialNullPoint;
-            } else if (controlPointIndex == 0 && !s.getShowName()) {
+            } else if (controlPointIndex == 0 && !s.shouldShowName()) {
                 cur = new Point(cur.x, cur.y - SLOT_OFFSET);
-            } else if (controlPointIndex == controlPoints.size() - 1 && !c.getInputSlot().getShowName()) {
+            } else if (controlPointIndex == controlPoints.size() - 1 && !c.getInputSlot().shouldShowName()) {
                 cur = new Point(cur.x, cur.y + SLOT_OFFSET);
             }
 
@@ -814,44 +807,62 @@
 
             LineWidget newPredecessor = predecessor;
             if (p == specialNullPoint) {
-
             } else if (lastPoint == specialNullPoint) {
-
             } else if (lastPoint != null) {
                 Point p1 = new Point(lastPoint.x + offx, lastPoint.y + offy);
                 Point p2 = new Point(p.x + offx, p.y + offy);
-                LineWidget w = new LineWidget(this, s, connectionList, p1, p2, predecessor, animator, isBold, isDashed);
+
+                Pair<Point, Point> curPair = new Pair<Point, Point>(p1, p2);
+                SceneAnimator curAnimator = animator;
+                if (lastLineCache.contains(curPair)) {
+                    curAnimator = null;
+                }
+                LineWidget w = new LineWidget(this, s, connectionList, p1, p2, predecessor, curAnimator, isBold, isDashed);
+                lineCache.add(curPair);
+
                 newPredecessor = w;
                 connectionLayer.addChild(w);
+                this.addObject(new ConnectionSet(connectionList), w);
                 w.getActions().addAction(hoverAction);
             }
 
-            processOutputSlot(s, connectionList, controlPointIndex + 1, p, newPredecessor, offx, offy, animator);
+            processOutputSlot(lastLineCache, s, connectionList, controlPointIndex + 1, p, newPredecessor, offx, offy, animator);
         }
     }
 
-    private void clearSelection() {
-        if (selectedWidgets.size() == 0) {
-            return;
+    private class ConnectionSet {
+
+        private Set<Connection> connections;
+
+        public ConnectionSet(Collection<Connection> connections) {
+            connections = new HashSet<Connection>(connections);
         }
-        for (FigureWidget w : selectedWidgets) {
-            assert w.getState().isSelected();
-            w.setState(w.getState().deriveSelected(false));
-            content.remove(w.getNode());
+
+        public Set<Connection> getConnectionSet() {
+            return Collections.unmodifiableSet(connections);
         }
-        selectedWidgets.clear();
     }
 
+    @Override
     public Lookup getLookup() {
         return lookup;
     }
 
+    public void initialize() {
+        Figure f = getModel().getDiagramToView().getRootFigure();
+        if (f != null) {
+            setUndoRedoEnabled(false);
+            gotoFigure(f);
+            setUndoRedoEnabled(true);
+        }
+    }
+
     public void gotoFigures(final List<Figure> figures) {
         Rectangle overall = null;
-        showFigures(figures);
+        getModel().showFigures(figures);
         for (Figure f : figures) {
 
-            FigureWidget fw = getFigureWidget(f);
+            FigureWidget fw = getWidget(f);
             if (fw != null) {
                 Rectangle r = fw.getBounds();
                 Point p = fw.getLocation();
@@ -869,6 +880,54 @@
         }
     }
 
+    private Set<Object> idSetToObjectSet(Set<Object> ids) {
+
+        Set<Object> result = new HashSet<Object>();
+        for (Figure f : getModel().getDiagramToView().getFigures()) {
+            if (DiagramScene.doesIntersect(f.getSource().getSourceNodesAsSet(), ids)) {
+                result.add(f);
+            }
+
+            for (Slot s : f.getSlots()) {
+                if (DiagramScene.doesIntersect(s.getSource().getSourceNodesAsSet(), ids)) {
+                    result.add(s);
+                }
+            }
+        }
+        return result;
+    }
+
+    public void gotoSelection(Set<Object> ids) {
+
+        Rectangle overall = null;
+        Set<Integer> hiddenNodes = new HashSet<Integer>(this.getModel().getHiddenNodes());
+        hiddenNodes.removeAll(ids);
+        this.getModel().showNot(hiddenNodes);
+
+        Set<Object> objects = idSetToObjectSet(ids);
+        for (Object o : objects) {
+
+            Widget w = getWidget(o);
+            if (w != null) {
+                Rectangle r = w.getBounds();
+                Point p = w.convertLocalToScene(new Point(0, 0));
+
+                Rectangle r2 = new Rectangle(p.x, p.y, r.width, r.height);
+
+                if (overall == null) {
+                    overall = r2;
+                } else {
+                    overall = overall.union(r2);
+                }
+            }
+        }
+        if (overall != null) {
+            centerRectangle(overall);
+        }
+
+        setSelectedObjects(objects);
+    }
+
     private Point calcCenter(Rectangle r) {
 
         Point center = new Point((int) r.getCenterX(), (int) r.getCenterY());
@@ -909,63 +968,8 @@
         }
     }
 
-    private void addToSelection(Figure f) {
-        FigureWidget w = getFigureWidget(f);
-        addToSelection(w);
-    }
-
-    private void addToSelection(FigureWidget w) {
-        assert !selectedWidgets.contains(w);
-        selectedWidgets.add(w);
-        content.add(w.getNode());
-        w.setState(w.getState().deriveSelected(true));
-    }
-
-    private void setSelection(Set<Integer> nodes) {
-        clearSelection();
-        for (Figure f : getModel().getDiagramToView().getFigures()) {
-            if (doesIntersect(f.getSource().getSourceNodesAsSet(), nodes)) {
-                addToSelection(f);
-            }
-        }
-        selectionUpdated();
-        this.validate();
-    }
-
     public void setSelection(Collection<Figure> list) {
-        clearSelection();
-        for (Figure f : list) {
-            addToSelection(f);
-        }
-
-        selectionUpdated();
-        this.validate();
-    }
-
-    public Set<Figure> getSelectedFigures() {
-        Set<Figure> result = new HashSet<Figure>();
-        for (Widget w : selectedWidgets) {
-            if (w instanceof FigureWidget) {
-                FigureWidget fw = (FigureWidget) w;
-                if (fw.getState().isSelected()) {
-                    result.add(fw.getFigure());
-                }
-            }
-        }
-        return result;
-    }
-
-    public Set<Integer> getSelectedNodes() {
-        Set<Integer> result = new HashSet<Integer>();
-        for (Widget w : selectedWidgets) {
-            if (w instanceof FigureWidget) {
-                FigureWidget fw = (FigureWidget) w;
-                if (fw.getState().isSelected()) {
-                    result.addAll(fw.getFigure().getSource().getSourceNodesAsSet());
-                }
-            }
-        }
-        return result;
+        super.setSelectedObjects(new HashSet<Figure>(list));
     }
 
     private UndoRedo.Manager getUndoRedoManager() {
@@ -990,7 +994,7 @@
         return true;
     }
 
-    private boolean doesIntersect(Set s1, Set s2) {
+    public static boolean doesIntersect(Set s1, Set s2) {
         if (s1.size() > s2.size()) {
             Set tmp = s1;
             s1 = s2;
@@ -1006,18 +1010,19 @@
         return false;
     }
 
-    public void showNot(final Set<Integer> nodes) {
-        updateHiddenNodes(nodes, true);
+    public void componentHidden() {
+        SelectionCoordinator.getInstance().getHighlightedChangedEvent().removeListener(highlightedCoordinatorListener);
+        SelectionCoordinator.getInstance().getSelectedChangedEvent().removeListener(selectedCoordinatorListener);
     }
 
-    public void showOnly(final Set<Integer> nodes) {
-        HashSet<Integer> allNodes = new HashSet<Integer>(getModel().getGraphToView().getGroup().getAllNodes());
-        allNodes.removeAll(nodes);
-        updateHiddenNodes(allNodes, true);
+    public void componentShowing() {
+        SelectionCoordinator.getInstance().getHighlightedChangedEvent().addListener(highlightedCoordinatorListener);
+        SelectionCoordinator.getInstance().getSelectedChangedEvent().addListener(selectedCoordinatorListener);
     }
 
     private void updateHiddenNodes(Set<Integer> newHiddenNodes, boolean doRelayout) {
 
+        System.out.println("newHiddenNodes: " + newHiddenNodes);
         Set<InputBlock> visibleBlocks = new HashSet<InputBlock>();
 
         Diagram diagram = getModel().getDiagramToView();
@@ -1026,15 +1031,15 @@
         Set<Widget> oldVisibleWidgets = new HashSet<Widget>();
 
         for (Figure f : diagram.getFigures()) {
-            FigureWidget w = figureWidgets.get(f);
-            if (w.isVisible()) {
+            FigureWidget w = getWidget(f);
+            if (w != null && w.isVisible()) {
                 oldVisibleWidgets.add(w);
             }
         }
 
         if (getModel().getShowBlocks()) {
             for (InputBlock b : diagram.getGraph().getBlocks()) {
-                BlockWidget w = blockWidgets.get(b);
+                BlockWidget w = getWidget(b);
                 if (w.isVisible()) {
                     oldVisibleWidgets.add(w);
                 }
@@ -1044,7 +1049,7 @@
         for (Figure f : diagram.getFigures()) {
             boolean hiddenAfter = doesIntersect(f.getSource().getSourceNodesAsSet(), newHiddenNodes);
 
-            FigureWidget w = this.figureWidgets.get(f);
+            FigureWidget w = getWidget(f);
             w.setBoundary(false);
             if (!hiddenAfter) {
                 // Figure is shown
@@ -1061,14 +1066,14 @@
         if (getModel().getShowNodeHull()) {
             List<FigureWidget> boundaries = new ArrayList<FigureWidget>();
             for (Figure f : diagram.getFigures()) {
-                FigureWidget w = this.figureWidgets.get(f);
+                FigureWidget w = getWidget(f);
                 if (!w.isVisible()) {
                     Set<Figure> set = new HashSet<Figure>(f.getPredecessorSet());
                     set.addAll(f.getSuccessorSet());
 
                     boolean b = false;
                     for (Figure neighbor : set) {
-                        FigureWidget neighborWidget = figureWidgets.get(neighbor);
+                        FigureWidget neighborWidget = getWidget(neighbor);
                         if (neighborWidget.isVisible()) {
                             b = true;
                             break;
@@ -1097,7 +1102,7 @@
 
                 boolean visibleAfter = visibleBlocks.contains(b);
 
-                BlockWidget w = blockWidgets.get(b);
+                BlockWidget w = getWidget(b);
                 if (visibleAfter) {
                     // Block must be shown
                     w.setVisible(true);
@@ -1108,7 +1113,6 @@
             }
         }
 
-        getModel().setHiddenNodes(newHiddenNodes);
         if (doRelayout) {
             relayout(oldVisibleWidgets);
         }
@@ -1116,45 +1120,39 @@
         addUndo();
     }
 
-    private void showFigures(Collection<Figure> f) {
-        HashSet<Integer> newHiddenNodes = new HashSet<Integer>(getModel().getHiddenNodes());
-        for (Figure fig : f) {
-            newHiddenNodes.removeAll(fig.getSource().getSourceNodesAsSet());
-        }
-        updateHiddenNodes(newHiddenNodes, true);
-    }
-
     private void showFigure(Figure f) {
         HashSet<Integer> newHiddenNodes = new HashSet<Integer>(getModel().getHiddenNodes());
         newHiddenNodes.removeAll(f.getSource().getSourceNodesAsSet());
         updateHiddenNodes(newHiddenNodes, true);
     }
 
-    public void showAll(final Collection<Figure> f) {
-        showFigures(f);
-
-    }
-
     public void show(final Figure f) {
         showFigure(f);
     }
 
+    public void setSelectedObjects(Object... args) {
+        Set<Object> set = new HashSet<Object>();
+        for (Object o : args) {
+            set.add(o);
+        }
+        super.setSelectedObjects(set);
+    }
+
+    private void centerWidget(Widget w) {
+        Rectangle r = w.getBounds();
+        Point p = w.getLocation();
+        centerRectangle(new Rectangle(p.x, p.y, r.width, r.height));
+    }
+
     public void gotoFigure(final Figure f) {
-
         if (!isVisible(f)) {
             showFigure(f);
         }
 
-        FigureWidget fw = getFigureWidget(f);
+        FigureWidget fw = getWidget(f);
         if (fw != null) {
-            Rectangle r = fw.getBounds();
-            Point p = fw.getLocation();
-            centerRectangle(new Rectangle(p.x, p.y, r.width, r.height));
-
-            // Select figure
-            clearSelection();
-            addToSelection(fw);
-            selectionUpdated();
+            centerWidget(fw);
+            setSelection(Arrays.asList(f));
         }
     }
 
@@ -1218,7 +1216,7 @@
 
         public void changed(DiagramViewModel source) {
             scene.getModel().getViewChangedEvent().removeListener(this);
-            if (oldModel.getSelectedNodes().equals(newModel.getHiddenNodes())) {
+            if (oldModel.getHiddenNodes().equals(newModel.getHiddenNodes())) {
                 scene.smallUpdate(false);
             } else {
                 scene.smallUpdate(true);
@@ -1235,11 +1233,30 @@
         return undoRedoEnabled;
     }
 
-    public void changed(DiagramViewModel source) {
-        assert source == model : "Receive only changed event from current model!";
-        assert source != null;
-        update();
-    }
+    private final ChangedListener<DiagramViewModel> fullChange = new ChangedListener<DiagramViewModel>() {
+        public void changed(DiagramViewModel source) {
+            assert source == model : "Receive only changed event from current model!";
+            assert source != null;
+            update();
+        }
+    };
+
+    private final ChangedListener<DiagramViewModel> hiddenNodesChange = new ChangedListener<DiagramViewModel>() {
+        public void changed(DiagramViewModel source) {
+            assert source == model : "Receive only changed event from current model!";
+            assert source != null;
+            smallUpdate(true);
+        }
+    };
+
+    private final ChangedListener<DiagramViewModel> selectionChange = new ChangedListener<DiagramViewModel>() {
+        public void changed(DiagramViewModel source) {
+            assert source == model : "Receive only changed event from current model!";
+            assert source != null;
+            smallUpdate(false);
+        }
+    };
+
 
     private void addUndo() {
 
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramViewModel.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramViewModel.java	Wed Jul 27 17:32:44 2011 -0700
@@ -38,8 +38,11 @@
 import java.util.List;
 import java.util.Set;
 import com.sun.hotspot.igv.data.ChangedListener;
+import com.sun.hotspot.igv.filter.CustomFilter;
+import com.sun.hotspot.igv.graph.Figure;
 import com.sun.hotspot.igv.settings.Settings;
 import java.awt.Color;
+import java.util.Collection;
 
 /**
  *
@@ -55,9 +58,11 @@
     private FilterChain filterChain;
     private FilterChain sequenceFilterChain;
     private Diagram diagram;
+    private InputGraph inputGraph;
     private ChangedEvent<DiagramViewModel> groupChangedEvent;
     private ChangedEvent<DiagramViewModel> diagramChangedEvent;
     private ChangedEvent<DiagramViewModel> viewChangedEvent;
+    private ChangedEvent<DiagramViewModel> hiddenNodesChangedEvent;
     private ChangedEvent<DiagramViewModel> viewPropertiesChangedEvent;
     private boolean showBlocks;
     private boolean showNodeHull;
@@ -100,7 +105,7 @@
         viewPropertiesChanged |= (showNodeHull != newModel.showNodeHull);
         this.showNodeHull = newModel.showNodeHull;
 
-        if(groupChanged) {
+        if (groupChanged) {
             groupChangedEvent.fire();
         }
 
@@ -149,7 +154,9 @@
         super.getChangedEvent().addListener(this);
         diagramChangedEvent = new ChangedEvent<DiagramViewModel>(this);
         viewChangedEvent = new ChangedEvent<DiagramViewModel>(this);
+        hiddenNodesChangedEvent = new ChangedEvent<DiagramViewModel>(this);
         viewPropertiesChangedEvent = new ChangedEvent<DiagramViewModel>(this);
+
         groupChangedEvent = new ChangedEvent<DiagramViewModel>(this);
         groupChangedEvent.addListener(groupChangedListener);
         groupChangedEvent.fire();
@@ -157,21 +164,18 @@
         filterChain.getChangedEvent().addListener(filterChainChangedListener);
         sequenceFilterChain.getChangedEvent().addListener(filterChainChangedListener);
     }
-
     private final ChangedListener<DiagramViewModel> groupChangedListener = new ChangedListener<DiagramViewModel>() {
 
         private Group oldGroup;
 
         public void changed(DiagramViewModel source) {
-            if(oldGroup != null) {
+            if (oldGroup != null) {
                 oldGroup.getChangedEvent().removeListener(groupContentChangedListener);
             }
             group.getChangedEvent().addListener(groupContentChangedListener);
             oldGroup = group;
         }
     };
-
-
     private final ChangedListener<Group> groupContentChangedListener = new ChangedListener<Group>() {
 
         public void changed(Group source) {
@@ -179,7 +183,6 @@
             setPositions(calculateStringList(source));
             setSelectedNodes(selectedNodes);
         }
-
     };
 
     public ChangedEvent<DiagramViewModel> getDiagramChangedEvent() {
@@ -190,20 +193,24 @@
         return viewChangedEvent;
     }
 
+    public ChangedEvent<DiagramViewModel> getHiddenNodesChangedEvent() {
+        return hiddenNodesChangedEvent;
+    }
+
     public ChangedEvent<DiagramViewModel> getViewPropertiesChangedEvent() {
         return viewPropertiesChangedEvent;
     }
 
     public Set<Integer> getSelectedNodes() {
-        return Collections.unmodifiableSet(selectedNodes);
+        return selectedNodes;
     }
 
     public Set<Integer> getHiddenNodes() {
-        return Collections.unmodifiableSet(hiddenNodes);
+        return hiddenNodes;
     }
 
     public Set<Integer> getOnScreenNodes() {
-        return Collections.unmodifiableSet(onScreenNodes);
+        return onScreenNodes;
     }
 
     public void setSelectedNodes(Set<Integer> nodes) {
@@ -242,15 +249,50 @@
                     index++;
                 }
             }
-            this.setColors(colors);
         }
         setColors(colors);
         viewChangedEvent.fire();
     }
 
+    public void showNot(final Set<Integer> nodes) {
+        System.out.println("Shownot called with " + nodes);
+        setHiddenNodes(nodes);
+    }
+
+    public void showFigures(Collection<Figure> f) {
+        HashSet<Integer> newHiddenNodes = new HashSet<Integer>(getHiddenNodes());
+        for (Figure fig : f) {
+            newHiddenNodes.removeAll(fig.getSource().getSourceNodesAsSet());
+        }
+        setHiddenNodes(newHiddenNodes);
+    }
+
+
+    public Set<Figure> getSelectedFigures() {
+        Set<Figure> result = new HashSet<Figure>();
+        for (Figure f : diagram.getFigures()) {
+            for (InputNode node : f.getSource().getSourceNodes()) {
+                if (getSelectedNodes().contains(node.getId())) {
+                    result.add(f);
+                }
+            }
+        }
+        return result;
+    }
+
+    public void showAll(final Collection<Figure> f) {
+        showFigures(f);
+    }
+
+    public void showOnly(final Set<Integer> nodes) {
+        final HashSet<Integer> allNodes = new HashSet<Integer>(getGraphToView().getGroup().getAllNodes());
+        allNodes.removeAll(nodes);
+        setHiddenNodes(allNodes);
+    }
+
     public void setHiddenNodes(Set<Integer> nodes) {
         this.hiddenNodes = nodes;
-        viewChangedEvent.fire();
+        hiddenNodesChangedEvent.fire();
     }
 
     public void setOnScreenNodes(Set<Integer> onScreenNodes) {
@@ -319,22 +361,41 @@
         if (diagram == null) {
             diagram = Diagram.createDiagram(getGraphToView(), Settings.get().get(Settings.NODE_TEXT, Settings.NODE_TEXT_DEFAULT));
             getFilterChain().apply(diagram, getSequenceFilterChain());
+            if (diagram.getGraph().getSourceGraphs() != null) {
+                CustomFilter f = new CustomFilter(
+                        "difference", "colorize('state', 'same', white);" +
+                        "colorize('state', 'changed', orange);" +
+                        "colorize('state', 'new', green);" +
+                        "colorize('state', 'deleted', red);");
+                f.apply(diagram);
+            }
         }
 
         return diagram;
     }
 
     public InputGraph getGraphToView() {
-        if (getFirstGraph() != getSecondGraph()) {
-            InputGraph inputGraph = Difference.createDiffGraph(getSecondGraph(), getFirstGraph());
-            return inputGraph;
-        } else {
-            InputGraph inputGraph = getFirstGraph();
-            return inputGraph;
+        if (inputGraph == null) {
+            if (getFirstGraph() != getSecondGraph()) {
+                inputGraph = Difference.createDiffGraph(getFirstGraph(), getSecondGraph());
+            } else {
+                inputGraph = getFirstGraph();
+            }
         }
+
+        return inputGraph;
     }
 
     public void changed(RangeSliderModel source) {
+        inputGraph = null;
         diagramChanged();
     }
+
+    void setSelectedFigures(List<Figure> list) {
+        Set<Integer> newSelectedNodes = new HashSet<Integer>();
+        for (Figure f : list) {
+            newSelectedNodes.addAll(f.getSource().getSourceNodesAsSet());
+        }
+        this.setSelectedNodes(newSelectedNodes);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramViewer.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package com.sun.hotspot.igv.view;
+
+import com.sun.hotspot.igv.graph.Figure;
+import java.awt.Component;
+import java.awt.Graphics2D;
+import java.util.Collection;
+import java.util.List;
+import javax.swing.JComponent;
+import org.openide.awt.UndoRedo;
+import org.openide.util.Lookup;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+interface DiagramViewer {
+
+    public void paint(Graphics2D svgGenerator);
+
+    public Lookup getLookup();
+
+    public JComponent createSatelliteView();
+
+    public Component getComponent();
+
+    public void zoomOut();
+
+    public void zoomIn();
+
+    public UndoRedo getUndoRedo();
+
+    public void componentHidden();
+
+    public void componentShowing();
+
+    public void initialize();
+    
+    public void setSelection(Collection<Figure> list);
+
+    public void centerFigures(List<Figure> list);
+
+}
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorInputGraphProvider.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorInputGraphProvider.java	Wed Jul 27 17:32:44 2011 -0700
@@ -35,18 +35,17 @@
  */
 public class EditorInputGraphProvider implements InputGraphProvider {
 
+    private EditorTopComponent editor;
+    
+    public EditorInputGraphProvider(EditorTopComponent editor) {
+        this.editor = editor;
+    }
+    
     public InputGraph getGraph() {
-        EditorTopComponent e = EditorTopComponent.getActive();
-        if (e == null) {
-            return null;
-        }
-        return e.getDiagramModel().getGraphToView();
+        return editor.getDiagramModel().getGraphToView();
     }
 
     public void setSelectedNodes(Set<InputNode> nodes) {
-        EditorTopComponent e = EditorTopComponent.getActive();
-        if (e != null) {
-            e.setSelectedNodes(nodes);
-        }
+        editor.setSelectedNodes(nodes);
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorTopComponent.form	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorTopComponent.form	Wed Jul 27 17:32:44 2011 -0700
@@ -18,6 +18,8 @@
   </NonVisualComponents>
   <AuxValues>
     <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
     <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
     <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
     <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="2"/>
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorTopComponent.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorTopComponent.java	Wed Jul 27 17:32:44 2011 -0700
@@ -23,6 +23,7 @@
  */
 package com.sun.hotspot.igv.view;
 
+import com.sun.hotspot.igv.data.ChangedEvent;
 import com.sun.hotspot.igv.data.InputNode;
 import com.sun.hotspot.igv.filter.FilterChain;
 import com.sun.hotspot.igv.graph.Diagram;
@@ -33,7 +34,6 @@
 import com.sun.hotspot.igv.view.actions.ExtractAction;
 import com.sun.hotspot.igv.view.actions.HideAction;
 import com.sun.hotspot.igv.view.actions.NextDiagramAction;
-import com.sun.hotspot.igv.view.actions.NodeFindAction;
 import com.sun.hotspot.igv.view.actions.OverviewAction;
 import com.sun.hotspot.igv.view.actions.PredSuccAction;
 import com.sun.hotspot.igv.view.actions.PrevDiagramAction;
@@ -43,16 +43,16 @@
 import com.sun.hotspot.igv.data.ChangedListener;
 import com.sun.hotspot.igv.data.Properties;
 import com.sun.hotspot.igv.data.Properties.PropertyMatcher;
+import com.sun.hotspot.igv.data.services.InputGraphProvider;
 import com.sun.hotspot.igv.filter.FilterChainProvider;
+import com.sun.hotspot.igv.graph.services.DiagramProvider;
 import com.sun.hotspot.igv.util.RangeSlider;
-import com.sun.hotspot.igv.util.RangeSliderModel;
 import com.sun.hotspot.igv.svg.BatikSVG;
+import com.sun.hotspot.igv.util.LookupHistory;
 import java.awt.BorderLayout;
 import java.awt.CardLayout;
 import java.awt.Color;
-import java.awt.Dimension;
 import java.awt.Graphics2D;
-import java.awt.Point;
 import java.awt.event.HierarchyBoundsListener;
 import java.awt.event.HierarchyEvent;
 import java.awt.event.KeyEvent;
@@ -67,18 +67,18 @@
 import java.io.UnsupportedEncodingException;
 import java.io.Writer;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 import javax.swing.Action;
-import javax.swing.ActionMap;
+import javax.swing.JComponent;
 import javax.swing.JPanel;
 import javax.swing.JToggleButton;
 import javax.swing.SwingUtilities;
 import javax.swing.UIManager;
 import javax.swing.border.Border;
 import org.openide.DialogDisplayer;
-import org.openide.actions.FindAction;
 import org.openide.actions.RedoAction;
 import org.openide.actions.UndoAction;
 import org.openide.awt.Toolbar;
@@ -86,8 +86,6 @@
 import org.openide.awt.UndoRedo;
 import org.openide.util.Lookup;
 import org.openide.util.NbBundle;
-import org.openide.util.actions.CallbackSystemAction;
-import org.openide.util.actions.SystemAction;
 import org.openide.util.lookup.AbstractLookup;
 import org.openide.util.lookup.InstanceContent;
 import org.openide.util.lookup.ProxyLookup;
@@ -97,19 +95,19 @@
 import org.openide.NotifyDescriptor;
 
 /**
- *
+ * 
  * @author Thomas Wuerthinger
  */
-public final class EditorTopComponent extends TopComponent implements ChangedListener<RangeSliderModel>, PropertyChangeListener {
+public final class EditorTopComponent extends TopComponent implements PropertyChangeListener {
 
-    private DiagramScene scene;
+    private DiagramViewer scene;
     private InstanceContent content;
-    private FindPanel findPanel;
+    private InstanceContent graphContent;
     private EnableBlockLayoutAction blockLayoutAction;
     private OverviewAction overviewAction;
     private PredSuccAction predSuccAction;
     private boolean notFirstTime;
-    private ExtendedSatelliteComponent satelliteComponent;
+    private JComponent satelliteComponent;
     private JPanel centerPanel;
     private CardLayout cardLayout;
     private RangeSlider rangeSlider;
@@ -152,12 +150,29 @@
         }
     };
 
+    private DiagramProvider diagramProvider = new DiagramProvider() {
+
+        public Diagram getDiagram() {
+            return getModel().getDiagramToView();
+        }
+
+        public ChangedEvent<DiagramProvider> getChangedEvent() {
+            return diagramChangedEvent;
+        }
+    };
+
+    private ChangedEvent<DiagramProvider> diagramChangedEvent = new ChangedEvent<DiagramProvider>(diagramProvider);
+    
+
     private void updateDisplayName() {
         setDisplayName(getDiagram().getName());
     }
 
     public EditorTopComponent(Diagram diagram) {
 
+        LookupHistory.init(InputGraphProvider.class);
+        LookupHistory.init(DiagramProvider.class);
+        this.setFocusable(true);
         FilterChain filterChain = null;
         FilterChain sequence = null;
         FilterChainProvider provider = Lookup.getDefault().lookup(FilterChainProvider.class);
@@ -190,8 +205,6 @@
 
         initComponents();
 
-        ActionMap actionMap = getActionMap();
-
         ToolbarPool.getDefault().setPreferredIconSize(16);
         Toolbar toolBar = new Toolbar();
         Border b = (Border) UIManager.get("Nb.Editor.Toolbar.border"); //NOI18N
@@ -202,24 +215,22 @@
         container.add(BorderLayout.NORTH, toolBar);
 
         rangeSliderModel = new DiagramViewModel(diagram.getGraph().getGroup(), filterChain, sequence);
-        rangeSliderModel.selectGraph(diagram.getGraph());
         rangeSlider = new RangeSlider();
         rangeSlider.setModel(rangeSliderModel);
-        rangeSliderModel.getChangedEvent().addListener(this);
         container.add(BorderLayout.CENTER, rangeSlider);
 
         scene = new DiagramScene(actions, rangeSliderModel);
         content = new InstanceContent();
-        this.associateLookup(new ProxyLookup(new Lookup[]{scene.getLookup(), new AbstractLookup(content)}));
+        graphContent = new InstanceContent();
+        this.associateLookup(new ProxyLookup(new Lookup[]{scene.getLookup(), new AbstractLookup(graphContent), new AbstractLookup(content)}));
         content.add(exportCookie);
         content.add(rangeSliderModel);
+        content.add(diagramProvider);
+
+        rangeSliderModel.getDiagramChangedEvent().addListener(diagramChangedListener);
+        rangeSliderModel.selectGraph(diagram.getGraph());
 
 
-        findPanel = new FindPanel(diagram.getFigures());
-        findPanel.setMaximumSize(new Dimension(200, 50));
-        toolBar.add(findPanel);
-        toolBar.add(NodeFindAction.get(NodeFindAction.class));
-        toolBar.addSeparator();
         toolBar.add(NextDiagramAction.get(NextDiagramAction.class));
         toolBar.add(PrevDiagramAction.get(PrevDiagramAction.class));
         toolBar.addSeparator();
@@ -256,44 +267,37 @@
         this.add(centerPanel, BorderLayout.CENTER);
         cardLayout = new CardLayout();
         centerPanel.setLayout(cardLayout);
-        centerPanel.add(SCENE_STRING, scene.getScrollPane());
+        centerPanel.add(SCENE_STRING, scene.getComponent());
         centerPanel.setBackground(Color.WHITE);
-        satelliteComponent = new ExtendedSatelliteComponent(scene);
+        satelliteComponent = scene.createSatelliteView();
         satelliteComponent.setSize(200, 200);
         centerPanel.add(SATELLITE_STRING, satelliteComponent);
 
-        CallbackSystemAction callFindAction = (CallbackSystemAction) SystemAction.get(FindAction.class);
-        NodeFindAction findAction = NodeFindAction.get(NodeFindAction.class);
-        Object key = callFindAction.getActionMapKey();
-        actionMap.put(key, findAction);
+        // TODO: Fix the hot key for entering the satellite view
+        this.addKeyListener(keyListener);
 
-        scene.getScrollPane().addKeyListener(keyListener);
-        scene.getView().addKeyListener(keyListener);
-        satelliteComponent.addKeyListener(keyListener);
-
-        scene.getScrollPane().addHierarchyBoundsListener(new HierarchyBoundsListener() {
+        scene.getComponent().addHierarchyBoundsListener(new HierarchyBoundsListener() {
 
             public void ancestorMoved(HierarchyEvent e) {
             }
 
             public void ancestorResized(HierarchyEvent e) {
-                if (!notFirstTime && scene.getScrollPane().getBounds().width > 0) {
+                if (!notFirstTime && scene.getComponent().getBounds().width > 0) {
                     notFirstTime = true;
                     SwingUtilities.invokeLater(new Runnable() {
 
                         public void run() {
-                            Figure f = EditorTopComponent.this.scene.getModel().getDiagramToView().getRootFigure();
-                            if (f != null) {
-                                scene.setUndoRedoEnabled(false);
-                                scene.gotoFigure(f);
-                                scene.setUndoRedoEnabled(true);
-                            }
+                            EditorTopComponent.this.scene.initialize();
                         }
                     });
                 }
             }
         });
 
+        if (diagram.getGraph().getGroup().getGraphs().size() == 1) {
+            rangeSlider.setVisible(false);
+        }
+
         updateDisplayName();
     }
     private KeyListener keyListener = new KeyListener() {
@@ -317,7 +321,7 @@
     };
 
     public DiagramViewModel getDiagramModel() {
-        return scene.getModel();
+        return rangeSliderModel;
     }
 
     private void showSatellite() {
@@ -328,35 +332,15 @@
 
     private void showScene() {
         cardLayout.show(centerPanel, SCENE_STRING);
-        scene.getView().requestFocus();
-    }
-
-    public void findNode() {
-        findPanel.find();
+        scene.getComponent().requestFocus();
     }
 
     public void zoomOut() {
-        double zoom = scene.getZoomFactor();
-        Point viewPosition = scene.getScrollPane().getViewport().getViewPosition();
-        double newZoom = zoom / DiagramScene.ZOOM_INCREMENT;
-        if (newZoom > DiagramScene.ZOOM_MIN_FACTOR) {
-            scene.setZoomFactor(newZoom);
-            scene.validate();
-            scene.getScrollPane().getViewport().setViewPosition(new Point((int) (viewPosition.x / DiagramScene.ZOOM_INCREMENT), (int) (viewPosition.y / DiagramScene.ZOOM_INCREMENT)));
-            this.satelliteComponent.update();
-        }
+        scene.zoomOut();
     }
 
     public void zoomIn() {
-        double zoom = scene.getZoomFactor();
-        Point viewPosition = scene.getScrollPane().getViewport().getViewPosition();
-        double newZoom = zoom * DiagramScene.ZOOM_INCREMENT;
-        if (newZoom < DiagramScene.ZOOM_MAX_FACTOR) {
-            scene.setZoomFactor(newZoom);
-            scene.validate();
-            scene.getScrollPane().getViewport().setViewPosition(new Point((int) (viewPosition.x * DiagramScene.ZOOM_INCREMENT), (int) (viewPosition.y * DiagramScene.ZOOM_INCREMENT)));
-            this.satelliteComponent.update();
-        }
+        scene.zoomIn();
     }
 
     public void showPrevDiagram() {
@@ -370,11 +354,11 @@
     }
 
     public DiagramViewModel getModel() {
-        return scene.getModel();
+        return rangeSliderModel;
     }
 
     public FilterChain getFilterChain() {
-        return this.scene.getModel().getFilterChain();
+        return getModel().getFilterChain();
     }
 
     public static EditorTopComponent getActive() {
@@ -407,6 +391,7 @@
         // Variables declaration - do not modify//GEN-BEGIN:variables
         private javax.swing.JCheckBox jCheckBox1;
         // End of variables declaration//GEN-END:variables
+
     @Override
     public int getPersistenceType() {
         return TopComponent.PERSISTENCE_NEVER;
@@ -425,9 +410,17 @@
         return PREFERRED_ID;
     }
 
-    public void changed(RangeSliderModel model) {
-        updateDisplayName();
-    }
+    private ChangedListener<DiagramViewModel> diagramChangedListener = new ChangedListener<DiagramViewModel>() {
+
+        public void changed(DiagramViewModel source) {
+            updateDisplayName();
+            Collection<Object> list = new ArrayList<Object>();
+            list.add(new EditorInputGraphProvider(EditorTopComponent.this));
+            graphContent.set(list, null);
+            diagramProvider.getChangedEvent().fire();
+        }
+        
+    };
 
     public boolean showPredSucc() {
         return (Boolean) predSuccAction.getValue(PredSuccAction.STATE);
@@ -435,13 +428,14 @@
 
     public void setSelection(PropertyMatcher matcher) {
 
-        Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<Figure>(scene.getModel().getDiagramToView().getFigures());
+        Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<Figure>(getModel().getDiagramToView().getFigures());
         List<Figure> list = selector.selectMultiple(matcher);
-        boolean b = scene.getUndoRedoEnabled();
-        scene.setUndoRedoEnabled(false);
-        scene.gotoFigures(list);
-        scene.setUndoRedoEnabled(b);
+        setSelectedFigures(list);
+    }
+
+    public void setSelectedFigures(List<Figure> list) {
         scene.setSelection(list);
+        scene.centerFigures(list);
     }
 
     public void setSelectedNodes(Set<InputNode> nodes) {
@@ -452,7 +446,7 @@
             ids.add(n.getId());
         }
 
-        for (Figure f : scene.getModel().getDiagramToView().getFigures()) {
+        for (Figure f : getModel().getDiagramToView().getFigures()) {
             for (InputNode n : f.getSource().getSourceNodes()) {
                 if (ids.contains(n.getId())) {
                     list.add(f);
@@ -461,8 +455,7 @@
             }
         }
 
-        scene.gotoFigures(list);
-        scene.setSelection(list);
+        setSelectedFigures(list);
     }
 
     public void propertyChange(PropertyChangeEvent evt) {
@@ -478,7 +471,6 @@
             }
         } else if (evt.getSource() == this.blockLayoutAction) {
             boolean b = (Boolean) blockLayoutAction.getValue(EnableBlockLayoutAction.STATE);
-            System.out.println("Showblocks = " + b);
             this.getModel().setShowBlocks(b);
         } else {
             assert false : "Unknown event source";
@@ -486,18 +478,18 @@
     }
 
     public void extract() {
-        scene.showOnly(scene.getSelectedNodes());
+        getModel().showOnly(getModel().getSelectedNodes());
     }
 
     public void hideNodes() {
-        Set<Integer> selectedNodes = this.scene.getSelectedNodes();
-        HashSet<Integer> nodes = new HashSet<Integer>(scene.getModel().getHiddenNodes());
+        Set<Integer> selectedNodes = this.getModel().getSelectedNodes();
+        HashSet<Integer> nodes = new HashSet<Integer>(getModel().getHiddenNodes());
         nodes.addAll(selectedNodes);
-        this.scene.showNot(nodes);
+        this.getModel().showNot(nodes);
     }
 
     public void expandPredecessors() {
-        Set<Figure> oldSelection = scene.getSelectedFigures();
+        Set<Figure> oldSelection = getModel().getSelectedFigures();
         Set<Figure> figures = new HashSet<Figure>();
 
         for (Figure f : this.getDiagramModel().getDiagramToView().getFigures()) {
@@ -518,11 +510,11 @@
             }
         }
 
-        scene.showAll(figures);
+        getModel().showAll(figures);
     }
 
     public void expandSuccessors() {
-        Set<Figure> oldSelection = scene.getSelectedFigures();
+        Set<Figure> oldSelection = getModel().getSelectedFigures();
         Set<Figure> figures = new HashSet<Figure>();
 
         for (Figure f : this.getDiagramModel().getDiagramToView().getFigures()) {
@@ -543,11 +535,11 @@
             }
         }
 
-        scene.showAll(figures);
+        getModel().showAll(figures);
     }
 
     public void showAll() {
-        scene.showNot(new HashSet<Integer>());
+        getModel().showNot(new HashSet<Integer>());
     }
 
     public Diagram getDiagram() {
@@ -555,23 +547,27 @@
     }
 
     @Override
-    protected void componentActivated() {
+    protected void componentHidden() {
+        super.componentHidden();
+        scene.componentHidden();
+
     }
 
     @Override
-    public void requestFocus() {
-        super.requestFocus();
-        scene.getView().requestFocus();
+    protected void componentShowing() {
+        super.componentShowing();
+        scene.componentShowing();
     }
 
     @Override
-    public boolean requestFocusInWindow() {
-        super.requestFocusInWindow();
-        return scene.getView().requestFocusInWindow();
+    public void requestActive() {
+        super.requestActive();
+        scene.getComponent().requestFocus();
     }
 
     @Override
     public UndoRedo getUndoRedo() {
         return scene.getUndoRedo();
     }
+
 }
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/ExtendedPanAction.java	Tue Jun 28 10:57:38 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +0,0 @@
-/*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-package com.sun.hotspot.igv.view;
-
-import java.awt.Container;
-import java.awt.Dimension;
-import java.awt.Point;
-import org.netbeans.api.visual.widget.Scene;
-import org.netbeans.api.visual.widget.Widget;
-import org.netbeans.api.visual.action.WidgetAction;
-
-import java.awt.event.MouseEvent;
-import javax.swing.JComponent;
-import javax.swing.JScrollPane;
-import javax.swing.SwingUtilities;
-
-/**
- * @author David Kaspar
- * @author Thomas Wuerthinger
- */
-public class ExtendedPanAction extends WidgetAction.LockedAdapter {
-
-    private Scene scene;
-    private JScrollPane scrollPane;
-    private Point lastLocation;
-
-    protected boolean isLocked() {
-        return scrollPane != null;
-    }
-
-    @Override
-    public State mousePressed(Widget widget, WidgetMouseEvent event) {
-        if (event.getButton() == MouseEvent.BUTTON2 || event.getButton() == MouseEvent.BUTTON1 && ((event.getModifiers() & MouseEvent.CTRL_MASK) != 0)) {
-            scene = widget.getScene();
-            scrollPane = findScrollPane(scene.getView());
-            if (scrollPane != null) {
-                lastLocation = scene.convertSceneToView(widget.convertLocalToScene(event.getPoint()));
-                SwingUtilities.convertPointToScreen(lastLocation, scrollPane.getViewport().getView());
-                return State.createLocked(widget, this);
-            }
-        }
-        return State.REJECTED;
-    }
-
-    private JScrollPane findScrollPane(JComponent component) {
-        for (;;) {
-            if (component == null) {
-                return null;
-            }
-            if (component instanceof JScrollPane) {
-                return ((JScrollPane) component);
-            }
-            Container parent = component.getParent();
-            if (!(parent instanceof JComponent)) {
-                return null;
-            }
-            component = (JComponent) parent;
-        }
-    }
-
-    @Override
-    public State mouseReleased(Widget widget, WidgetMouseEvent event) {
-        boolean state = pan(widget, event.getPoint());
-        if (state) {
-            scrollPane = null;
-        }
-        return state ? State.createLocked(widget, this) : State.REJECTED;
-    }
-
-    @Override
-    public State mouseDragged(Widget widget, WidgetMouseEvent event) {
-        return pan(widget, event.getPoint()) ? State.createLocked(widget, this) : State.REJECTED;
-    }
-
-    private boolean pan(Widget widget, Point newLocation) {
-        if (scrollPane == null || scene != widget.getScene()) {
-            return false;
-        }
-        newLocation = scene.convertSceneToView(widget.convertLocalToScene(newLocation));
-        SwingUtilities.convertPointToScreen(newLocation, scrollPane.getViewport().getView());
-        Point viewPosition = scrollPane.getViewport().getViewPosition();
-        Dimension viewSize = scrollPane.getViewport().getViewSize();
-        Dimension viewPortSize = scrollPane.getViewport().getSize();
-
-        int xOffset = lastLocation.x - newLocation.x;
-        int yOffset = lastLocation.y - newLocation.y;
-
-        if (viewPortSize.height == viewSize.height) {
-            yOffset = 0;
-        }
-
-        if (viewPortSize.width == viewSize.width) {
-            xOffset = 0;
-        }
-
-        if (xOffset == 0 && yOffset == 0) {
-            return true;
-        }
-        viewPosition = new Point(viewPosition.x + xOffset, viewPosition.y + yOffset);
-        viewPosition.x = Math.max(viewPosition.x, 0);
-        viewPosition.y = Math.max(viewPosition.y, 0);
-        viewPosition.x = Math.min(viewPosition.x, scrollPane.getViewport().getView().getSize().width - scrollPane.getViewport().getSize().width);
-        viewPosition.y = Math.min(viewPosition.y, scrollPane.getViewport().getView().getSize().height - scrollPane.getViewport().getSize().height);
-
-        scrollPane.getViewport().setViewPosition(viewPosition);
-        scrollPane.getViewport().getView().repaint();
-        lastLocation = newLocation;
-        return true;
-    }
-}
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/ExtendedSatelliteComponent.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/ExtendedSatelliteComponent.java	Wed Jul 27 17:32:44 2011 -0700
@@ -97,9 +97,10 @@
             image = this.createImage(imageWidth, imageHeight);
             Graphics2D ig = (Graphics2D) image.getGraphics();
             ig.scale(scale, scale);
-            scene.setRealZoomFactor(scale);
+	    double oldFactor = scene.getZoomFactor();
+	    scene.setZoomFactor(scale);
             scene.paint(ig);
-            scene.setRealZoomFactor(0.0);
+	    scene.setZoomFactor(oldFactor);
         }
 
         gr.drawImage(image, vx, vy, this);
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/FindPanel.java	Tue Jun 28 10:57:38 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-/*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-package com.sun.hotspot.igv.view;
-
-import com.sun.hotspot.igv.graph.Figure;
-import com.sun.hotspot.igv.data.Properties;
-import com.sun.hotspot.igv.data.Properties.RegexpPropertyMatcher;
-import com.sun.hotspot.igv.data.Property;
-import java.awt.GridLayout;
-import java.awt.event.KeyEvent;
-import java.awt.event.KeyListener;
-import java.util.List;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import javax.swing.JComboBox;
-import javax.swing.JPanel;
-import javax.swing.JTextField;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-class FindPanel extends JPanel implements KeyListener {
-
-    private JComboBox nameComboBox;
-    private JTextField valueTextField;
-
-    public FindPanel(List<Figure> figures) {
-        createDesign();
-        updateComboBox(figures);
-    }
-
-    protected void createDesign() {
-        setLayout(new GridLayout());
-        nameComboBox = new JComboBox();
-        valueTextField = new JTextField();
-        add(nameComboBox);
-        add(valueTextField);
-        valueTextField.addKeyListener(this);
-    }
-
-    public void updateComboBox(List<Figure> figures) {
-
-        String sel = (String) nameComboBox.getSelectedItem();
-        SortedSet<String> propertyNames = new TreeSet<String>();
-
-        for (Figure f : figures) {
-            Properties prop = f.getProperties();
-            for (Property p : prop) {
-                if (!propertyNames.contains(p.getName())) {
-                    propertyNames.add(p.getName());
-                }
-            }
-        }
-
-        for (String s : propertyNames) {
-            nameComboBox.addItem(s);
-        }
-        nameComboBox.setSelectedItem(sel);
-    }
-
-    public String getNameText() {
-        return (String) nameComboBox.getSelectedItem();
-    }
-
-    public String getValueText() {
-        return valueTextField.getText();
-    }
-
-    public void keyTyped(KeyEvent e) {
-    }
-
-    public void keyPressed(KeyEvent e) {
-        if (e.getKeyCode() == KeyEvent.VK_ENTER) {
-            find();
-        }
-    }
-
-    public void find() {
-        EditorTopComponent comp = EditorTopComponent.getActive();
-        if (comp != null) {
-            RegexpPropertyMatcher matcher = new RegexpPropertyMatcher(getNameText(), getValueText());
-            comp.setSelection(matcher);
-        }
-    }
-
-    public void keyReleased(KeyEvent e) {
-
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/NodeQuickSearch.java	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.view;
+
+import com.sun.hotspot.igv.data.InputGraph;
+import com.sun.hotspot.igv.data.InputNode;
+import com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.data.Properties.RegexpPropertyMatcher;
+import com.sun.hotspot.igv.data.Property;
+import com.sun.hotspot.igv.data.services.InputGraphProvider;
+import com.sun.hotspot.igv.util.LookupHistory;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Pattern;
+import org.netbeans.spi.quicksearch.SearchProvider;
+import org.netbeans.spi.quicksearch.SearchRequest;
+import org.netbeans.spi.quicksearch.SearchResponse;
+import org.openide.DialogDisplayer;
+import org.openide.NotifyDescriptor;
+import org.openide.NotifyDescriptor.Message;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class NodeQuickSearch implements SearchProvider {
+
+    private static final String DEFAULT_PROPERTY = "name";
+
+    /**
+     * Method is called by infrastructure when search operation was requested.
+     * Implementors should evaluate given request and fill response object with
+     * apropriate results
+     *
+     * @param request Search request object that contains information what to search for
+     * @param response Search response object that stores search results. Note that it's important to react to return value of SearchResponse.addResult(...) method and stop computation if false value is returned.
+     */
+    public void evaluate(SearchRequest request, SearchResponse response) {
+        String query = request.getText();
+        if (query.trim().isEmpty()) {
+            return;
+        }
+
+        final String[] parts = query.split("=", 2);
+
+        String name;
+        String value;
+
+        if (parts.length == 1) {
+            name = DEFAULT_PROPERTY;
+            value = ".*" + Pattern.quote(parts[0]) + ".*";
+        } else {
+            name = parts[0];
+            value = parts[1];
+        }
+
+        if (value.isEmpty()) {
+            value = ".*";
+        }
+
+        final InputGraphProvider p = LookupHistory.getLast(InputGraphProvider.class);
+        if (p != null && p.getGraph() != null) {
+            List<InputNode> matches = null;
+            try {
+                RegexpPropertyMatcher matcher = new RegexpPropertyMatcher(name, value, Pattern.CASE_INSENSITIVE);
+                Properties.PropertySelector<InputNode> selector = new Properties.PropertySelector<InputNode>(p.getGraph().getNodes());
+
+                matches = selector.selectMultiple(matcher);
+            } catch (Exception e) {
+                final String msg = e.getMessage();
+                response.addResult(new Runnable() {
+                        public void run() {
+                            Message desc = new NotifyDescriptor.Message("An exception occurred during the search, "
+                                    + "perhaps due to a malformed query string:\n" + msg,
+                                    NotifyDescriptor.WARNING_MESSAGE);
+                            DialogDisplayer.getDefault().notify(desc);
+                        }
+                    },
+                    "(Error during search)"
+                );
+            }
+
+            if (matches != null) {
+                final Set<InputNode> set = new HashSet<InputNode>(matches);
+                response.addResult(new Runnable() {
+                        public void run() {
+                            final EditorTopComponent comp = EditorTopComponent.getActive();
+                            if (comp != null) {
+                                comp.setSelectedNodes(set);
+                                comp.requestActive();
+                            }
+                        }
+                    },
+                    "All " + matches.size() + " matching nodes (" + name + "=" + value + ")"
+                );
+
+                // Single matches
+                for (final InputNode n : matches) {
+                    response.addResult(new Runnable() {
+                            public void run() {
+                                final EditorTopComponent comp = EditorTopComponent.getActive();
+                                if (comp != null) {
+                                    final Set<InputNode> tmpSet = new HashSet<InputNode>();
+                                    tmpSet.add(n);
+                                    comp.setSelectedNodes(tmpSet);
+                                    comp.requestActive();
+                                }
+                            }
+                        },
+                        n.getProperties().get(name) + " (" + n.getId() + " " + n.getProperties().get("name") + ")"
+                    );
+                }
+            }
+        } else {
+            System.out.println("no input graph provider!");
+        }
+    }
+}
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/PreferenceConstants.java	Tue Jun 28 10:57:38 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-package com.sun.hotspot.igv.view;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public class PreferenceConstants {
-
-    public static final String KEY_LINE_GENERATOR = "lineGenerator";
-    public static final String DEFAULT_LINE_GENERATOR = "com.sun.hotspot.igv.positioning.BasicLineGenerator";
-}
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/SlotLayout.java	Tue Jun 28 10:57:38 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,171 +0,0 @@
-/*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-package com.sun.hotspot.igv.view;
-
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.util.Collection;
-import java.util.List;
-import org.netbeans.api.visual.layout.Layout;
-import org.netbeans.api.visual.layout.LayoutFactory;
-import org.netbeans.api.visual.widget.Widget;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public class SlotLayout implements Layout {
-
-    public enum HorizontalAlignment {
-
-        Left,
-        Center,
-        Right
-    }
-    private Layout baseLayout;
-    private HorizontalAlignment alignment;
-    private boolean vertical;
-
-    public SlotLayout() {
-        this(HorizontalAlignment.Center, false);
-    }
-
-    public SlotLayout(HorizontalAlignment alignment, boolean vertical) {
-        this.alignment = alignment;
-        baseLayout = LayoutFactory.createVerticalFlowLayout();
-        this.vertical = vertical;
-    }
-
-    public void layout(Widget widget) {
-        if (!vertical) {
-            Collection<Widget> children = widget.getChildren();
-            int gap = 0;
-            int max = 0;
-            for (Widget child : children) {
-                Rectangle preferredBounds = child.getPreferredBounds();
-                int i = preferredBounds.width;
-                if (i > max) {
-                    max = i;
-                }
-            }
-            int pos = 0;
-            for (Widget child : children) {
-                Rectangle preferredBounds = child.getPreferredBounds();
-                int x = preferredBounds.x;
-                int y = preferredBounds.y;
-                int width = preferredBounds.width;
-                int height = preferredBounds.height;
-                if (pos == 0) {
-                    pos += height / 2;
-                }
-                int lx = -x;
-                int ly = pos - y;
-                switch (alignment) {
-                    case Center:
-                        lx += (max - width) / 2;
-                        break;
-                    case Left:
-                        break;
-                    case Right:
-                        lx += max - width;
-                        break;
-                }
-                child.resolveBounds(new Point(lx, ly), new Rectangle(x, y, width, height));
-                pos += height + gap;
-            }
-        } else {
-
-            Collection<Widget> children = widget.getChildren();
-            int gap = 0;
-            int max = 0;
-            for (Widget child : children) {
-                Rectangle preferredBounds = child.getPreferredBounds();
-                int i = preferredBounds.height;
-                if (i > max) {
-                    max = i;
-                }
-            }
-            int pos = 0;
-            for (Widget child : children) {
-                Rectangle preferredBounds = child.getPreferredBounds();
-                int x = preferredBounds.x;
-                int y = preferredBounds.y;
-                int width = preferredBounds.width;
-                int height = preferredBounds.height;
-                if (pos == 0) {
-                    pos += width / 2;
-                }
-                int lx = pos - x;
-                int ly = -y;
-                switch (alignment) {
-                    case Center:
-                        ly += (max - height) / 2;
-                        break;
-                    case Left:
-                        break;
-                    case Right:
-                        ly += max - height;
-                        break;
-                }
-                child.resolveBounds(new Point(lx, ly), new Rectangle(x, y, width, height));
-                pos += width + gap;
-            }
-
-        }
-    }
-
-    public boolean requiresJustification(Widget widget) {
-        return true;
-    }
-
-    public void justify(Widget widget) {
-        baseLayout.justify(widget);
-
-        Rectangle client = widget.getClientArea();
-        List<Widget> children = widget.getChildren();
-
-        int count = children.size();
-        int z = 0;
-
-        int maxWidth = 0;
-        for (Widget c : children) {
-            if (c.getPreferredBounds().width > maxWidth) {
-                maxWidth = c.getPreferredBounds().width;
-            }
-        }
-
-        for (Widget c : children) {
-            z++;
-            Point curLocation = c.getLocation();
-            Rectangle curBounds = c.getBounds();
-
-
-            Point location = new Point(curLocation.x, client.y + client.height * z / (count + 1) - curBounds.height / 2);
-            if (vertical) {
-                location = new Point(client.x + client.width * z / (count + 1) - maxWidth / 2, curLocation.y);
-            }
-            c.resolveBounds(location, null);
-        }
-    }
-}
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/EnableBlockLayoutAction.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/EnableBlockLayoutAction.java	Wed Jul 27 17:32:44 2011 -0700
@@ -27,6 +27,7 @@
 import javax.swing.AbstractAction;
 import javax.swing.Action;
 import javax.swing.ImageIcon;
+import org.openide.util.ImageUtilities;
 
 /**
  *
@@ -39,7 +40,7 @@
 
     public EnableBlockLayoutAction() {
         state = true;
-        putValue(AbstractAction.SMALL_ICON, new ImageIcon(org.openide.util.Utilities.loadImage(iconResource())));
+        putValue(AbstractAction.SMALL_ICON, new ImageIcon(ImageUtilities.loadImage(iconResource())));
         putValue(STATE, true);
         putValue(Action.SHORT_DESCRIPTION, "Cluster nodes into blocks");
     }
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ExpandPredecessorsAction.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ExpandPredecessorsAction.java	Wed Jul 27 17:32:44 2011 -0700
@@ -41,7 +41,7 @@
     }
 
     public String getName() {
-        return "Expand Predecessors";
+        return "Expand Above";
     }
 
     @Override
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ExpandSuccessorsAction.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ExpandSuccessorsAction.java	Wed Jul 27 17:32:44 2011 -0700
@@ -41,7 +41,7 @@
     }
 
     public String getName() {
-        return "Expand Successors";
+        return "Expand Below";
     }
 
     @Override
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ExportAction.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ExportAction.java	Wed Jul 27 17:32:44 2011 -0700
@@ -103,7 +103,7 @@
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/view/images/export.gif";
+        return "com/sun/hotspot/igv/view/images/export.png";
     }
 
     public HelpCtx getHelpCtx() {
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/NextDiagramAction.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/NextDiagramAction.java	Wed Jul 27 17:32:44 2011 -0700
@@ -29,6 +29,7 @@
 import javax.swing.Action;
 import javax.swing.ImageIcon;
 import org.openide.util.HelpCtx;
+import org.openide.util.ImageUtilities;
 import org.openide.util.Lookup;
 import org.openide.util.NbBundle;
 import org.openide.util.Utilities;
@@ -47,7 +48,7 @@
 
     public NextDiagramAction(Lookup lookup) {
         putValue(Action.SHORT_DESCRIPTION, "Show next graph of current group");
-        putValue(Action.SMALL_ICON, new ImageIcon(Utilities.loadImage("com/sun/hotspot/igv/view/images/next_diagram.png")));
+        putValue(Action.SMALL_ICON, new ImageIcon(ImageUtilities.loadImage("com/sun/hotspot/igv/view/images/next_diagram.png")));
     }
 
     public String getName() {
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/NodeFindAction.java	Tue Jun 28 10:57:38 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-package com.sun.hotspot.igv.view.actions;
-
-import com.sun.hotspot.igv.view.EditorTopComponent;
-import javax.swing.Action;
-import org.openide.util.HelpCtx;
-import org.openide.util.NbBundle;
-import org.openide.util.actions.CallableSystemAction;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public final class NodeFindAction extends CallableSystemAction {
-
-    public void performAction() {
-        EditorTopComponent comp = EditorTopComponent.getActive();
-        if (comp != null) {
-            comp.findNode();
-        }
-    }
-
-    public NodeFindAction() {
-        putValue(Action.SHORT_DESCRIPTION, "Find nodes");
-    }
-
-    public String getName() {
-        return NbBundle.getMessage(NodeFindAction.class, "CTL_NodeFindAction");
-    }
-
-    public HelpCtx getHelpCtx() {
-        return HelpCtx.DEFAULT_HELP;
-    }
-
-    @Override
-    protected boolean asynchronous() {
-        return false;
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return true;
-    }
-
-    @Override
-    protected String iconResource() {
-        return "com/sun/hotspot/igv/view/images/search.gif";
-    }
-}
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/OverviewAction.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/OverviewAction.java	Wed Jul 27 17:32:44 2011 -0700
@@ -27,6 +27,7 @@
 import javax.swing.AbstractAction;
 import javax.swing.Action;
 import javax.swing.ImageIcon;
+import org.openide.util.ImageUtilities;
 
 /**
  *
@@ -38,7 +39,7 @@
     public static final String STATE = "state";
 
     public OverviewAction() {
-        putValue(AbstractAction.SMALL_ICON, new ImageIcon(org.openide.util.Utilities.loadImage(iconResource())));
+        putValue(AbstractAction.SMALL_ICON, new ImageIcon(ImageUtilities.loadImage(iconResource())));
         putValue(Action.SHORT_DESCRIPTION, "Show satellite view of whole graph");
         setState(false);
     }
@@ -53,6 +54,6 @@
     }
 
     protected String iconResource() {
-        return "com/sun/hotspot/igv/view/images/overview.gif";
+        return "com/sun/hotspot/igv/view/images/overview.png";
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/PredSuccAction.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/PredSuccAction.java	Wed Jul 27 17:32:44 2011 -0700
@@ -27,6 +27,7 @@
 import javax.swing.AbstractAction;
 import javax.swing.Action;
 import javax.swing.ImageIcon;
+import org.openide.util.ImageUtilities;
 
 /**
  *
@@ -39,7 +40,7 @@
 
     public PredSuccAction() {
         state = true;
-        putValue(AbstractAction.SMALL_ICON, new ImageIcon(org.openide.util.Utilities.loadImage(iconResource())));
+        putValue(AbstractAction.SMALL_ICON, new ImageIcon(ImageUtilities.loadImage(iconResource())));
         putValue(STATE, true);
         putValue(Action.SHORT_DESCRIPTION, "Show neighboring nodes of fully visible nodes semi-transparent");
     }
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/PrevDiagramAction.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/PrevDiagramAction.java	Wed Jul 27 17:32:44 2011 -0700
@@ -29,6 +29,7 @@
 import javax.swing.Action;
 import javax.swing.ImageIcon;
 import org.openide.util.HelpCtx;
+import org.openide.util.ImageUtilities;
 import org.openide.util.Lookup;
 import org.openide.util.NbBundle;
 import org.openide.util.Utilities;
@@ -47,7 +48,7 @@
 
     public PrevDiagramAction(Lookup lookup) {
         putValue(Action.SHORT_DESCRIPTION, "Show previous graph of current group");
-        putValue(Action.SMALL_ICON, new ImageIcon(Utilities.loadImage("com/sun/hotspot/igv/view/images/prev_diagram.png")));
+        putValue(Action.SMALL_ICON, new ImageIcon(ImageUtilities.loadImage("com/sun/hotspot/igv/view/images/prev_diagram.png")));
     }
 
     public String getName() {
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ZoomInAction.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ZoomInAction.java	Wed Jul 27 17:32:44 2011 -0700
@@ -64,6 +64,6 @@
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/view/images/zoomin.gif";
+        return "com/sun/hotspot/igv/view/images/zoom_in.png";
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ZoomOutAction.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ZoomOutAction.java	Wed Jul 27 17:32:44 2011 -0700
@@ -70,6 +70,6 @@
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/view/images/zoomout.gif";
+        return "com/sun/hotspot/igv/view/images/zoom_out.png";
     }
 }
Binary file src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/export.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/export.png has changed
Binary file src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/overview.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/overview.png has changed
Binary file src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/search.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/zoom_in.png has changed
Binary file src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/zoom_out.png has changed
Binary file src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/zoomin.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/zoomout.gif has changed
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/layer.xml	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/layer.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -51,6 +51,17 @@
             </file>
         </folder>
     </folder>
+
+    
+    <folder name="QuickSearch">
+        <folder name="Nodes">
+            <attr name="command" stringvalue="n"/>
+            <attr name="position" intvalue="0"/>
+            <file name="com-sun-hotspot-igv-view-NodeQuickSearch.instance">
+                <attr name="SystemFileSystem.localizingBundle" stringvalue="com.sun.hotspot.igv.view.Bundle"/>
+            </file>
+        </folder>
+    </folder>
     <folder name="Toolbars">
         <folder name="Edit">
             <attr name="com-sun-hotspot-igv-view-actions-LineGeneratorAction.shadow/com-sun-hotspot-igv-coordinator-actions-OpenGraphAction.shadow" boolvalue="true"/>
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/BlockWidget.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/BlockWidget.java	Wed Jul 27 17:32:44 2011 -0700
@@ -74,7 +74,7 @@
         g.setColor(titleColor);
         g.setFont(titleFont);
 
-        String s = "B" + blockNode.toString();
+        String s = "B" + blockNode.getName();
         Rectangle2D r1 = g.getFontMetrics().getStringBounds(s, g);
         g.drawString(s, r.x + 5, r.y + (int) r1.getHeight());
         g.setStroke(old);
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/DiagramConnectionWidget.java	Tue Jun 28 10:57:38 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,251 +0,0 @@
-/*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-package com.sun.hotspot.igv.view.widgets;
-
-import com.sun.hotspot.igv.graph.Connection;
-import com.sun.hotspot.igv.graph.Figure;
-import com.sun.hotspot.igv.view.DiagramScene;
-import java.awt.BasicStroke;
-import java.awt.Color;
-import java.awt.Composite;
-import java.awt.Graphics2D;
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.awt.Stroke;
-import java.util.ArrayList;
-import java.util.List;
-import org.netbeans.api.visual.anchor.AnchorShape;
-import org.netbeans.api.visual.model.ObjectState;
-import org.netbeans.api.visual.widget.ConnectionWidget;
-import org.netbeans.api.visual.widget.Scene;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public class DiagramConnectionWidget extends ConnectionWidget {
-
-    private static Stroke DASHED_STROKE = new BasicStroke(
-            1,
-            BasicStroke.CAP_BUTT,
-            BasicStroke.JOIN_ROUND,
-            0,
-            new float[]{2},
-            0);
-    private static Stroke NORMAL_STROKE = new BasicStroke(1);
-    private static Stroke BOLD_STROKE = new BasicStroke(3);
-    public static int WHITE_FACTOR = 5;
-    private Connection connection;
-    private Color color;
-    private Point lastSourceAnchor;
-    private Point lastTargetAnchor;
-    private List<Point> controlPoints;
-    private Rectangle clientArea;
-    private boolean split;
-    private int[] xPoints;
-    private int[] yPoints;
-    private int pointCount;
-
-    /** Creates a new instance of ConnectionWidget */
-    public DiagramConnectionWidget(Connection connection, Scene scene) {
-        super(scene);
-        this.connection = connection;
-        color = connection.getColor();
-        if (connection.getStyle() == Connection.ConnectionStyle.DASHED) {
-            this.setStroke(DASHED_STROKE);
-        } else if (connection.getStyle() == Connection.ConnectionStyle.BOLD) {
-            this.setStroke(BOLD_STROKE);
-        } else {
-            this.setStroke(NORMAL_STROKE);
-        }
-        this.setCheckClipping(true);
-        clientArea = new Rectangle();
-        updateControlPoints();
-    }
-
-    public Connection getConnection() {
-        return connection;
-    }
-
-    public void updateControlPoints() {
-        List<Point> newControlPoints = connection.getControlPoints();
-        Connection c = connection;
-        Figure f = c.getInputSlot().getFigure();
-        Point p = new Point(f.getPosition());
-        p.translate(c.getInputSlot().getRelativePosition().x, f.getSize().height / 2);
-        Point p4 = new Point(f.getPosition());
-        p4.translate(c.getInputSlot().getRelativePosition().x, c.getInputSlot().getRelativePosition().y);
-
-        Figure f2 = c.getOutputSlot().getFigure();
-        Point p2 = new Point(f2.getPosition());
-        p2.translate(c.getOutputSlot().getRelativePosition().x, f2.getSize().height / 2);
-        Point p3 = new Point(f2.getPosition());
-        p3.translate(c.getOutputSlot().getRelativePosition().x, c.getOutputSlot().getRelativePosition().y);
-
-        /*if(controlPoints.size() >= 2) {
-        String className = Preferences.userNodeForPackage(PreferenceConstants.class).get(PreferenceConstants.KEY_LINE_GENERATOR, PreferenceConstants.DEFAULT_LINE_GENERATOR);
-        try {
-        LineGenerator lg = (LineGenerator)Class.forName(className).newInstance();
-        controlPoints = lg.createLine(controlPoints, p2, p);
-        } catch (InstantiationException ex) {
-        } catch (IllegalAccessException ex) {
-        } catch (ClassNotFoundException ex) {
-        }
-        }*/
-
-        this.controlPoints = newControlPoints;
-        pointCount = newControlPoints.size();
-        xPoints = new int[pointCount];
-        yPoints = new int[pointCount];
-        int minX = Integer.MAX_VALUE;
-        int maxX = Integer.MIN_VALUE;
-        int minY = Integer.MAX_VALUE;
-        int maxY = Integer.MIN_VALUE;
-        split = false;
-        for (int i = 0; i < pointCount; i++) {
-            if (newControlPoints.get(i) == null) {
-                split = true;
-            } else {
-                int curX = newControlPoints.get(i).x;
-                int curY = newControlPoints.get(i).y;
-                this.xPoints[i] = curX;
-                this.yPoints[i] = curY;
-                minX = Math.min(minX, curX);
-                maxX = Math.max(maxX, curX);
-                minY = Math.min(minY, curY);
-                maxY = Math.max(maxY, curY);
-            }
-        }
-
-        this.clientArea = new Rectangle(minX, minY, maxX - minX, maxY - minY);
-    }
-
-    @Override
-    protected void paintWidget() {
-        Graphics2D g = this.getGraphics();
-
-        if (xPoints.length == 0 || Math.abs(xPoints[0] - xPoints[xPoints.length - 1]) > 2000) {
-            return;
-        }
-
-        //g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
-        //g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
-        //g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
-
-        DiagramScene ds = (DiagramScene) this.getScene();
-        boolean shouldHide = false;//ds.getShouldHide(this);
-
-        Composite oldComposite = null;
-        if (shouldHide) {
-            Color c = new Color(255 - (255 - color.getRed()) / WHITE_FACTOR, 255 - (255 - color.getGreen()) / WHITE_FACTOR, 255 - (255 - color.getBlue()) / WHITE_FACTOR);
-            g.setPaint(c);
-        } else {
-            g.setPaint(color);
-        }
-
-        if (split) {
-            for (int i = 1; i < controlPoints.size(); i++) {
-                Point prev = controlPoints.get(i - 1);
-                Point cur = controlPoints.get(i);
-                if (cur == null || prev == null) {
-                    continue;
-                }
-
-                g.drawLine(prev.x, prev.y, cur.x, cur.y);
-            }
-        } else {
-            g.drawPolyline(xPoints, yPoints, pointCount);
-        }
-
-        /*for(int i=0; i<xPoints.length; i++) {
-        int x = xPoints[i];
-        int y = yPoints[i];
-        g.fillOval(x - 2, y - 2, 4, 4);
-        }*/
-
-        if (xPoints.length >= 2) {
-            Graphics2D g2 = (Graphics2D) g.create();
-            int xOff = xPoints[xPoints.length - 2] - xPoints[xPoints.length - 1];
-            int yOff = yPoints[yPoints.length - 2] - yPoints[yPoints.length - 1];
-            if (xOff == 0 && yOff == 0 && yPoints.length >= 3) {
-                xOff = xPoints[xPoints.length - 3] - xPoints[xPoints.length - 1];
-                yOff = yPoints[yPoints.length - 3] - yPoints[yPoints.length - 1];
-            }
-            g2.translate(xPoints[xPoints.length - 1], yPoints[yPoints.length - 1]);
-            g2.rotate(Math.atan2(yOff, xOff));
-
-            g2.scale(0.55, 0.80);
-            AnchorShape.TRIANGLE_FILLED.paint(g2, false);
-        }
-    }
-
-    @Override
-    public void notifyStateChanged(ObjectState previousState, ObjectState state) {
-
-        if (previousState.isHovered() != state.isHovered()) {
-            color = connection.getColor();
-            if (state.isHovered()) {
-                this.setStroke(BOLD_STROKE);
-            } else {
-                this.setStroke(NORMAL_STROKE);
-            }
-
-            if (state.isHovered()) {
-                this.setStroke(BOLD_STROKE);
-            } else {
-                this.setStroke(NORMAL_STROKE);
-            }
-
-            repaint();
-        }
-        super.notifyStateChanged(previousState, state);
-    }
-
-    @Override
-    public List<Point> getControlPoints() {
-        if (split) {
-            ArrayList<Point> result = new ArrayList<Point>();
-            for (Point p : controlPoints) {
-                if (p != null) {
-                    result.add(p);
-                }
-            }
-            return result;
-        } else {
-            return controlPoints;
-        }
-    }
-
-    @Override
-    public String toString() {
-        return "ConnectionWidget[" + connection + "]";
-    }
-
-    @Override
-    protected Rectangle calculateClientArea() {
-        Rectangle result = new Rectangle(clientArea);
-        result.grow(10, 10);
-        return result;
-    }
-}
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/FigureWidget.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/FigureWidget.java	Wed Jul 27 17:32:44 2011 -0700
@@ -25,17 +25,17 @@
 
 import com.sun.hotspot.igv.graph.Figure;
 import com.sun.hotspot.igv.view.DiagramScene;
-import com.sun.hotspot.igv.view.SlotLayout;
 import com.sun.hotspot.igv.util.DoubleClickHandler;
 import com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.util.DoubleClickAction;
 import com.sun.hotspot.igv.util.PropertiesSheet;
 import java.awt.AlphaComposite;
 import java.awt.Color;
 import java.awt.Composite;
 import java.awt.Dimension;
 import java.awt.Font;
-import java.awt.Graphics;
 import java.awt.Point;
+import java.awt.Rectangle;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.Set;
@@ -62,7 +62,7 @@
 
     public static final boolean VERTICAL_LAYOUT = true;
     public static final int DEPTH = 5;
-    public static final int MAX_STRING_LENGTH = 20;
+    //public static final int MAX_STRING_LENGTH = 20;
     private static final double LABEL_ZOOM_FACTOR = 0.3;
     private static final double ZOOM_FACTOR = 0.1;
     private Font font;
@@ -75,6 +75,7 @@
     private DiagramScene diagramScene;
     private boolean boundary;
     private Node node;
+    private Widget dummyTop;
 
     public void setBoundary(boolean b) {
         boundary = b;
@@ -88,80 +89,69 @@
         return node;
     }
 
-    private String shortenString(String string) {
-        if (string.length() > MAX_STRING_LENGTH) {
-            StringBuilder sb = new StringBuilder();
-            for (int i = 0; i < string.length(); i++) {
-                char c = string.charAt(i);
-                if (!Character.isLetter(c) || Character.isUpperCase(c)) {
-                    sb.append(c);
-                }
-            }
-            string = sb.toString();
-        }
-        return string;
-    }
+	@Override
+	public boolean isHitAt(Point localLocation) {
+		return middleWidget.isHitAt(localLocation);
+	}
+    
 
-    public FigureWidget(final Figure f, DiagramScene s, Widget parent) {
+    public FigureWidget(final Figure f, WidgetAction hoverAction, WidgetAction selectAction, DiagramScene scene, Widget parent) {
+
+        super(scene);
 
-        super(s);
+        assert this.getScene() != null;
+        assert this.getScene().getView() != null;
 
-
+        this.figure = f;
         font = f.getDiagram().getFont();
         boldFont = f.getDiagram().getFont().deriveFont(Font.BOLD);
         this.setCheckClipping(true);
-        this.diagramScene = s;
-
+        this.diagramScene = scene;
         parent.addChild(this);
-        this.figure = f;
-        this.resolveBounds(null, calculateClientArea());
-
-        leftWidget = new Widget(s);
-        this.addChild(leftWidget);
-        leftWidget.setLayout(new SlotLayout(SlotLayout.HorizontalAlignment.Right, VERTICAL_LAYOUT));//LayoutFactory.createVerticalFlowLayout(LayoutFactory.SerialAlignment.JUSTIFY, 0));
 
-        middleWidget = new Widget(s);
-        this.addChild(middleWidget);
-
-        if (VERTICAL_LAYOUT) {
-            this.setLayout(LayoutFactory.createVerticalFlowLayout());
-        } else {
-            this.setLayout(LayoutFactory.createHorizontalFlowLayout());
-        }
-
-        middleWidget.setLayout(LayoutFactory.createVerticalFlowLayout());
-
+	Widget outer = new Widget(scene);
+	outer.setBackground(f.getColor());
+	outer.setLayout(LayoutFactory.createOverlayLayout());
+	
+        middleWidget = new Widget(scene);
+        middleWidget.setLayout(LayoutFactory.createVerticalFlowLayout(LayoutFactory.SerialAlignment.CENTER, 0));
         middleWidget.setBackground(f.getColor());
         middleWidget.setOpaque(true);
-        assert this.getScene() != null;
-        assert this.getScene().getView() != null;
-        middleWidget.setBorder(BorderFactory.createLineBorder(Color.BLACK));
-
+        //middleWidget.setBorder(BorderFactory.createLineBorder(Color.BLACK));
+        middleWidget.getActions().addAction(new DoubleClickAction(this));
+	middleWidget.setCheckClipping(true);
 
         labelWidgets = new ArrayList<LabelWidget>();
 
         String[] strings = figure.getLines();
 
+        dummyTop = new Widget(scene);
+        dummyTop.setMinimumSize(new Dimension(Figure.INSET / 2, 1));
+        middleWidget.addChild(dummyTop);
+
+
         for (String cur : strings) {
 
             String displayString = cur;
 
-            LabelWidget lw = new LabelWidget(s);
+            LabelWidget lw = new LabelWidget(scene);
             labelWidgets.add(lw);
             middleWidget.addChild(lw);
             lw.setLabel(displayString);
-
             lw.setFont(font);
             lw.setForeground(Color.BLACK);
             lw.setAlignment(LabelWidget.Alignment.CENTER);
             lw.setVerticalAlignment(LabelWidget.VerticalAlignment.CENTER);
-            lw.setMaximumSize(new Dimension(f.getWidth(), 20000));
-            lw.setMinimumSize(new Dimension(f.getWidth(), 20));
+	    lw.setBorder(BorderFactory.createEmptyBorder());
         }
 
-        rightWidget = new Widget(s);
-        this.addChild(rightWidget);
-        rightWidget.setLayout(new SlotLayout(SlotLayout.HorizontalAlignment.Left, VERTICAL_LAYOUT));//LayoutFactory.createVerticalLayout(LayoutFactory.SerialAlignment.JUSTIFY, 0));
+        Widget dummyBottom = new Widget(scene);
+        dummyBottom.setMinimumSize(new Dimension(Figure.INSET / 2, 1));
+        middleWidget.addChild(dummyBottom);
+
+        middleWidget.setPreferredBounds(new Rectangle(0, Figure.SLOT_WIDTH - Figure.OVERLAPPING, f.getWidth(), f.getHeight()));
+	//outer.addChild(middleWidget);
+        this.addChild(middleWidget);
 
         // Initialize node for property sheet
         node = new AbstractNode(Children.LEAF) {
@@ -175,22 +165,6 @@
         };
         node.setDisplayName(getName());
     }
-    private boolean firstTime = true;
-
-    @Override
-    protected void paintWidget() {
-        if (firstTime) {
-            firstTime = false;
-            for (LabelWidget w : labelWidgets) {
-                String cur = w.getLabel();
-                Graphics graphics = this.getGraphics();
-                if (graphics.getFontMetrics().stringWidth(cur) > figure.getWidth()) {
-                    w.setLabel(shortenString(cur));
-                }
-            }
-        }
-        super.paintWidget();
-    }
 
     public Widget getLeftWidget() {
         return leftWidget;
@@ -205,19 +179,34 @@
         super.notifyStateChanged(previousState, state);
 
         Color borderColor = Color.BLACK;
+	Color innerBorderColor = getFigure().getColor();
         int thickness = 1;
         boolean repaint = false;
         Font f = font;
-        if (state.isSelected()) {
-            thickness = 1;
+        if (state.isSelected() || state.isHighlighted()) {
+            thickness = 2;
+	}
+	if(state.isSelected()) {
             f = boldFont;
-        }
+		innerBorderColor = borderColor;
+        } else {
+	}
 
-        if (state.isHovered()) {
-            borderColor = Color.BLUE;
-        }
+        if (state.isHighlighted()) {
+		innerBorderColor = borderColor = Color.BLUE;
+		repaint = true;
+        } else {
+		repaint = true;
+	}
 
         if (state.isHovered() != previousState.isHovered()) {
+
+		/*
+            if (state.isHovered()) {
+                diagramScene.addAllHighlighted(this.getFigure().getSource().getSourceNodesAsSet());
+            } else {
+                diagramScene.removeAllHighlighted(this.getFigure().getSource().getSourceNodesAsSet());
+            }*/
             repaint = true;
         }
 
@@ -226,7 +215,7 @@
         }
 
         if (repaint) {
-            middleWidget.setBorder(BorderFactory.createLineBorder(borderColor, thickness));
+            middleWidget.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(borderColor, 1), BorderFactory.createLineBorder(innerBorderColor, 1)));
             for (LabelWidget labelWidget : labelWidgets) {
                 labelWidget.setFont(f);
             }
@@ -249,7 +238,7 @@
     @Override
     protected void paintChildren() {
 
-        if (diagramScene.getRealZoomFactor() < ZOOM_FACTOR && diagramScene.getModel().getShowBlocks()) {
+        if (diagramScene.getZoomFactor() < ZOOM_FACTOR && diagramScene.getModel().getShowBlocks()) {
             return;
         }
 
@@ -260,7 +249,7 @@
             this.getScene().getGraphics().setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
         }
 
-        if (diagramScene.getRealZoomFactor() < LABEL_ZOOM_FACTOR) {
+        if (diagramScene.getZoomFactor() < LABEL_ZOOM_FACTOR) {
 
             for (LabelWidget labelWidget : labelWidgets) {
                 labelWidget.setVisible(false);
@@ -282,10 +271,10 @@
     public JPopupMenu getPopupMenu(Widget widget, Point point) {
         JPopupMenu m = diagramScene.createPopupMenu();
 
-        JMenu predecessors = new JMenu("Predecessors");
+        JMenu predecessors = new JMenu("Nodes Above");
         addFigureToSubMenu(predecessors, getFigure(), false, DEPTH);
 
-        JMenu successors = new JMenu("Successors");
+        JMenu successors = new JMenu("Nodes Below");
         addFigureToSubMenu(successors, getFigure(), true, DEPTH);
 
         m.addSeparator();
@@ -319,16 +308,13 @@
     }
 
     public void addFigureToMenu(JMenu m, final Figure f, boolean successor, int depth) {
-
         Action a = diagramScene.createGotoAction(f);
-
-
         m.add(a);
 
         if (depth > 0) {
-            String name = "Predecessors";
+            String name = "Nodes Above";
             if (successor) {
-                name = "Successors";
+                name = "Nodes Below";
             }
 
             JMenu subMenu = new JMenu(name);
@@ -341,18 +327,18 @@
     public void handleDoubleClick(Widget w, WidgetAction.WidgetMouseEvent e) {
 
         if (diagramScene.isAllVisible()) {
-            Set<Integer> hiddenNodes = new HashSet<Integer>(diagramScene.getModel().getGraphToView().getGroup().getAllNodes());
+            final Set<Integer> hiddenNodes = new HashSet<Integer>(diagramScene.getModel().getGraphToView().getGroup().getAllNodes());
             hiddenNodes.removeAll(this.getFigure().getSource().getSourceNodesAsSet());
-            this.diagramScene.showNot(hiddenNodes);
+            this.diagramScene.getModel().showNot(hiddenNodes);
         } else if (isBoundary()) {
 
-            Set<Integer> hiddenNodes = new HashSet<Integer>(diagramScene.getModel().getHiddenNodes());
+            final Set<Integer> hiddenNodes = new HashSet<Integer>(diagramScene.getModel().getHiddenNodes());
             hiddenNodes.removeAll(this.getFigure().getSource().getSourceNodesAsSet());
-            this.diagramScene.showNot(hiddenNodes);
+            this.diagramScene.getModel().showNot(hiddenNodes);
         } else {
-            Set<Integer> hiddenNodes = new HashSet<Integer>(diagramScene.getModel().getHiddenNodes());
+            final Set<Integer> hiddenNodes = new HashSet<Integer>(diagramScene.getModel().getHiddenNodes());
             hiddenNodes.addAll(this.getFigure().getSource().getSourceNodesAsSet());
-            this.diagramScene.showNot(hiddenNodes);
+            this.diagramScene.getModel().showNot(hiddenNodes);
         }
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/InputSlotWidget.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/InputSlotWidget.java	Wed Jul 27 17:32:44 2011 -0700
@@ -23,6 +23,7 @@
  */
 package com.sun.hotspot.igv.view.widgets;
 
+import com.sun.hotspot.igv.graph.Figure;
 import com.sun.hotspot.igv.graph.InputSlot;
 import com.sun.hotspot.igv.view.DiagramScene;
 import java.awt.Point;
@@ -40,14 +41,24 @@
     public InputSlotWidget(InputSlot slot, DiagramScene scene, Widget parent, FigureWidget fw) {
         super(slot, scene, parent, fw);
         inputSlot = slot;
-        init();
-        getFigureWidget().getLeftWidget().addChild(this);
+        //init();
+        //getFigureWidget().getLeftWidget().addChild(this);
+        Point p = inputSlot.getRelativePosition();
+        p.x -= this.calculateClientArea().width / 2;
+        p.y += Figure.SLOT_START;
+        this.setPreferredLocation(p);
     }
 
     public InputSlot getInputSlot() {
         return inputSlot;
     }
-
+    
+    protected int calculateSlotWidth() {
+        List<InputSlot> slots = getSlot().getFigure().getInputSlots();
+        assert slots.contains(getSlot());
+        return calculateWidth(slots.size());
+    }
+/*
     protected Point calculateRelativeLocation() {
         if (getFigureWidget().getBounds() == null) {
             return new Point(0, 0);
@@ -57,5 +68,5 @@
         List<InputSlot> slots = inputSlot.getFigure().getInputSlots();
         assert slots.contains(inputSlot);
         return new Point((int) x, (int) (calculateRelativeY(slots.size(), slots.indexOf(inputSlot))));
-    }
+    }*/
 }
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/LineWidget.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/LineWidget.java	Wed Jul 27 17:32:44 2011 -0700
@@ -24,6 +24,7 @@
 package com.sun.hotspot.igv.view.widgets;
 
 import com.sun.hotspot.igv.graph.Connection;
+import com.sun.hotspot.igv.graph.Figure;
 import com.sun.hotspot.igv.graph.InputSlot;
 import com.sun.hotspot.igv.graph.OutputSlot;
 import com.sun.hotspot.igv.view.DiagramScene;
@@ -35,12 +36,15 @@
 import java.awt.Stroke;
 import java.awt.geom.Line2D;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import javax.swing.JPopupMenu;
 import javax.swing.event.PopupMenuEvent;
 import javax.swing.event.PopupMenuListener;
 import org.netbeans.api.visual.action.ActionFactory;
 import org.netbeans.api.visual.action.PopupMenuProvider;
+import org.netbeans.api.visual.action.SelectProvider;
 import org.netbeans.api.visual.animator.SceneAnimator;
 import org.netbeans.api.visual.model.ObjectState;
 import org.netbeans.api.visual.widget.Widget;
@@ -51,7 +55,7 @@
  */
 public class LineWidget extends Widget implements PopupMenuProvider {
 
-    public final int BORDER = 8;
+    public final int BORDER = 5;
     public final int ARROW_SIZE = 6;
     public final int BOLD_ARROW_SIZE = 7;
     public final int HOVER_ARROW_SIZE = 8;
@@ -111,6 +115,8 @@
             color = connections.get(0).getColor();
         }
 
+        this.setToolTipText("<HTML>" + generateToolTipText(this.connections) + "</HTML>");
+
         this.setCheckClipping(true);
 
         this.getActions().addAction(ActionFactory.createPopupMenuAction(this));
@@ -120,6 +126,35 @@
             this.setBackground(Color.WHITE);
             animator.animateBackgroundColor(this, color);
         }
+
+        this.getActions().addAction(ActionFactory.createSelectAction(new SelectProvider() {
+
+            public boolean isAimingAllowed(Widget arg0, Point arg1, boolean arg2) {
+                return true;
+            }
+
+            public boolean isSelectionAllowed(Widget arg0, Point arg1, boolean arg2) {
+                return true;
+            }
+
+            public void select(Widget arg0, Point arg1, boolean arg2) {
+                Set<Figure> set = new HashSet<Figure>();
+                for (Connection c : LineWidget.this.connections) {
+                    set.add(c.getInputSlot().getFigure());
+                    set.add(c.getOutputSlot().getFigure());
+                }
+                LineWidget.this.scene.setSelectedObjects(set);
+            }
+        }));
+    }
+
+    private String generateToolTipText(List<Connection> conn) {
+        StringBuilder sb = new StringBuilder();
+        for (Connection c : conn) {
+            sb.append(c.getToolTipText());
+            sb.append("<br>");
+        }
+        return sb.toString();
     }
 
     public Point getFrom() {
@@ -141,13 +176,12 @@
 
     @Override
     protected void paintWidget() {
-        if (scene.getRealZoomFactor() < ZOOM_FACTOR) {
+        if (scene.getZoomFactor() < ZOOM_FACTOR) {
             return;
         }
 
         Graphics2D g = getScene().getGraphics();
         g.setPaint(this.getBackground());
-        ObjectState state = this.getState();
         float width = 1.0f;
 
         if (isBold) {
@@ -207,6 +241,20 @@
 
     private void setHighlighted(boolean b) {
         this.highlighted = b;
+	Set<Object> highlightedObjects = new HashSet<Object>(scene.getHighlightedObjects());
+	Set<Object> highlightedObjectsChange = new HashSet<Object>();
+        for (Connection c : connections) {
+		highlightedObjectsChange.add(c.getInputSlot().getFigure());
+		highlightedObjectsChange.add(c.getInputSlot());
+		highlightedObjectsChange.add(c.getOutputSlot().getFigure());
+		highlightedObjectsChange.add(c.getOutputSlot());
+        }
+	if(b) {
+		highlightedObjects.addAll(highlightedObjectsChange);
+	} else {
+		highlightedObjects.removeAll(highlightedObjectsChange);
+	}
+	scene.setHighlightedObjects(highlightedObjects);
         this.revalidate(true);
     }
 
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/MultiConnectionWidget.java	Tue Jun 28 10:57:38 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,281 +0,0 @@
-/*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-package com.sun.hotspot.igv.view.widgets;
-
-import com.sun.hotspot.igv.graph.Connection;
-import com.sun.hotspot.igv.graph.InputSlot;
-import com.sun.hotspot.igv.graph.OutputSlot;
-import com.sun.hotspot.igv.graph.Slot;
-import com.sun.hotspot.igv.view.DiagramScene;
-import java.awt.BasicStroke;
-import java.awt.Color;
-import java.awt.Graphics2D;
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.awt.Stroke;
-import java.awt.geom.Line2D;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import javax.swing.JPopupMenu;
-import javax.swing.event.PopupMenuEvent;
-import javax.swing.event.PopupMenuListener;
-import org.netbeans.api.visual.action.PopupMenuProvider;
-import org.netbeans.api.visual.model.ObjectState;
-import org.netbeans.api.visual.widget.Widget;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public class MultiConnectionWidget extends Widget implements PopupMenuProvider {
-
-    public final int BORDER = 4;
-    public final int HOVER_STROKE_WIDTH = 3;
-
-    private static class Route {
-
-        public Point from;
-        public Point to;
-        public SortedSet<InputSlot> inputSlots;
-        public boolean decorateStart;
-        public boolean decorateEnd;
-
-        public Route(Point from, Point to) {
-            assert from != null;
-            assert to != null;
-            this.from = from;
-            this.to = to;
-            this.inputSlots = new TreeSet<InputSlot>();
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-
-            if (obj instanceof Route) {
-                Route r = (Route) obj;
-                return r.from.equals(from) && r.to.equals(to);
-            }
-
-            return super.equals(obj);
-        }
-
-        @Override
-        public int hashCode() {
-            return ((((from.x * 1711) + from.y) * 1711 + to.x) * 1711 + to.y);
-        }
-    }
-    private Rectangle clientArea;
-    private OutputSlot outputSlot;
-    private Map<Route, SortedSet<InputSlot>> routeMap;
-    private List<Route> routeList;
-    private Color color;
-    private DiagramScene diagramScene;
-    private boolean popupVisible;
-
-    /** Creates a new instance of MultiConnectionWidget */
-    public MultiConnectionWidget(OutputSlot outputSlot, DiagramScene scene) {
-        super(scene);
-
-        this.diagramScene = scene;
-        this.outputSlot = outputSlot;
-        this.setCheckClipping(true);
-
-        routeMap = new HashMap<Route, SortedSet<InputSlot>>();
-        routeList = new ArrayList<Route>();
-        color = Color.BLACK;
-
-        for (Connection c : outputSlot.getConnections()) {
-            List<Point> controlPoints = c.getControlPoints();
-            InputSlot inputSlot = (InputSlot) c.getTo();
-            color = c.getColor();
-
-            for (int i = 1; i < controlPoints.size(); i++) {
-                Point prev = controlPoints.get(i - 1);
-                Point cur = controlPoints.get(i);
-
-                if (prev != null && cur != null) {
-                    Route r = new Route(prev, cur);
-                    if (routeMap.containsKey(r)) {
-                        SortedSet<InputSlot> set = routeMap.get(r);
-                        set.add(inputSlot);
-                    } else {
-                        SortedSet<InputSlot> set = new TreeSet<InputSlot>(Slot.slotFigureComparator);
-                        set.add(inputSlot);
-                        routeMap.put(r, set);
-                        routeList.add(r);
-                    }
-                }
-            }
-        }
-
-        if (routeList.size() == 0) {
-            clientArea = new Rectangle();
-        } else {
-            for (Route r : routeList) {
-
-                int x = r.from.x;
-                int y = r.from.y;
-
-                int x2 = r.to.x;
-                int y2 = r.to.y;
-
-                if (x > x2) {
-                    int tmp = x;
-                    x = x2;
-                    x2 = tmp;
-                }
-
-                if (y > y2) {
-                    int tmp = y;
-                    y = y2;
-                    y2 = tmp;
-                }
-
-                int width = x2 - x + 1;
-                int height = y2 - y + 1;
-
-                Rectangle rect = new Rectangle(x, y, width, height);
-                if (clientArea == null) {
-                    clientArea = rect;
-                } else {
-                    clientArea = clientArea.union(rect);
-                }
-            }
-
-            clientArea.grow(BORDER, BORDER);
-        }
-    }
-
-    private void setHoverPosition(Point location) {
-        Route r = getNearest(location);
-    }
-
-    private Route getNearest(Point localLocation) {
-
-        double minDist = Double.MAX_VALUE;
-        Route result = null;
-        for (Route r : routeList) {
-            double dist = Line2D.ptSegDistSq((double) r.from.x, (double) r.from.y, (double) r.to.x, (double) r.to.y, (double) localLocation.x, (double) localLocation.y);
-            if (dist < minDist) {
-                result = r;
-                minDist = dist;
-            }
-        }
-
-        assert result != null;
-
-        return result;
-    }
-
-    @Override
-    public boolean isHitAt(Point localLocation) {
-        if (!super.isHitAt(localLocation)) {
-            return false;
-        }
-
-        for (Route r : routeList) {
-            double dist = Line2D.ptSegDistSq((double) r.from.x, (double) r.from.y, (double) r.to.x, (double) r.to.y, (double) localLocation.x, (double) localLocation.y);
-            if (dist < BORDER * BORDER) {
-                setHoverPosition(localLocation);
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    @Override
-    protected Rectangle calculateClientArea() {
-        return clientArea;
-    }
-
-    @Override
-    protected void paintWidget() {
-        Graphics2D g = getScene().getGraphics();
-        //g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
-        g.setColor(this.color);
-        ObjectState state = this.getState();
-        float width = 1.0f;
-        if (state.isHovered() || this.popupVisible) {
-            width = HOVER_STROKE_WIDTH;
-        }
-
-        Stroke oldStroke = g.getStroke();
-        g.setStroke(new BasicStroke(width));
-        for (Route r : routeList) {
-            g.drawLine(r.from.x, r.from.y, r.to.x, r.to.y);
-        }
-        g.setStroke(oldStroke);
-    }
-
-    @Override
-    protected void notifyStateChanged(ObjectState previousState, ObjectState state) {
-
-        boolean repaint = false;
-
-        if (state.isHovered() != previousState.isHovered()) {
-            repaint = true;
-        }
-
-        repaint();
-    }
-
-    public JPopupMenu getPopupMenu(Widget widget, Point localLocation) {
-        JPopupMenu menu = new JPopupMenu();
-        Route r = getNearest(localLocation);
-        assert r != null;
-        assert routeMap.containsKey(r);
-
-        menu.add(diagramScene.createGotoAction(outputSlot.getFigure()));
-        menu.addSeparator();
-
-        SortedSet<InputSlot> set = this.routeMap.get(r);
-        for (InputSlot s : set) {
-            menu.add(diagramScene.createGotoAction(s.getFigure()));
-        }
-
-        final MultiConnectionWidget w = this;
-        menu.addPopupMenuListener(new PopupMenuListener() {
-
-            public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
-                w.popupVisible = true;
-                w.repaint();
-            }
-
-            public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
-                w.popupVisible = false;
-                w.repaint();
-            }
-
-            public void popupMenuCanceled(PopupMenuEvent e) {
-            }
-        });
-
-        return menu;
-    }
-}
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/OutputSlotWidget.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/OutputSlotWidget.java	Wed Jul 27 17:32:44 2011 -0700
@@ -23,10 +23,12 @@
  */
 package com.sun.hotspot.igv.view.widgets;
 
+import com.sun.hotspot.igv.graph.Figure;
 import com.sun.hotspot.igv.graph.OutputSlot;
 import com.sun.hotspot.igv.view.DiagramScene;
 import java.awt.Point;
 import java.util.List;
+import org.netbeans.api.visual.widget.Scene;
 import org.netbeans.api.visual.widget.Widget;
 
 /**
@@ -40,14 +42,27 @@
     public OutputSlotWidget(OutputSlot slot, DiagramScene scene, Widget parent, FigureWidget fw) {
         super(slot, scene, parent, fw);
         outputSlot = slot;
-        init();
-        getFigureWidget().getRightWidget().addChild(this);
+        //init();
+        //getFigureWidget().getRightWidget().addChild(this);
+        Point p = outputSlot.getRelativePosition();
+        p.y += getSlot().getFigure().getHeight() - Figure.SLOT_START;
+        p.x -= this.calculateClientArea().width / 2;
+        //p.x += this.calculateClientArea().width / 2;
+        this.setPreferredLocation(p);
     }
 
     public OutputSlot getOutputSlot() {
         return outputSlot;
     }
 
+    protected int calculateSlotWidth() {
+        
+        List<OutputSlot> slots = getSlot().getFigure().getOutputSlots();
+        assert slots.contains(getSlot());
+        return calculateWidth(slots.size());
+        
+    }
+    /*
     protected Point calculateRelativeLocation() {
         if (getFigureWidget().getBounds() == null) {
             return new Point(0, 0);
@@ -57,5 +72,5 @@
         List<OutputSlot> slots = outputSlot.getFigure().getOutputSlots();
         assert slots.contains(outputSlot);
         return new Point((int) x, (int) (calculateRelativeY(slots.size(), slots.indexOf(outputSlot))));
-    }
+    }*/
 }
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/SlotWidget.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/SlotWidget.java	Wed Jul 27 17:32:44 2011 -0700
@@ -26,53 +26,52 @@
 import com.sun.hotspot.igv.graph.Figure;
 import com.sun.hotspot.igv.graph.OutputSlot;
 import com.sun.hotspot.igv.graph.Slot;
-import com.sun.hotspot.igv.view.*;
+import com.sun.hotspot.igv.selectioncoordinator.SelectionCoordinator;
+import com.sun.hotspot.igv.util.DoubleClickHandler;
+import com.sun.hotspot.igv.view.DiagramScene;
 import java.awt.Color;
 import java.awt.Font;
 import java.awt.Graphics2D;
-import java.awt.Image;
 import java.awt.Point;
 import java.awt.Rectangle;
 import java.awt.geom.Rectangle2D;
+import java.util.HashSet;
+import java.util.Set;
+import org.netbeans.api.visual.action.WidgetAction;
+import org.netbeans.api.visual.model.ObjectState;
 import org.netbeans.api.visual.widget.Widget;
 
 /**
  *
  * @author Thomas Wuerthinger
  */
-public abstract class SlotWidget extends Widget {
+public abstract class SlotWidget extends Widget implements DoubleClickHandler {
 
     private Slot slot;
     private FigureWidget figureWidget;
-    private Image bufferImage;
     private static double TEXT_ZOOM_FACTOR = 0.9;
     private static double ZOOM_FACTOR = 0.6;
-    private DiagramScene scene;
+    private DiagramScene diagramScene;
 
     public SlotWidget(Slot slot, DiagramScene scene, Widget parent, FigureWidget fw) {
         super(scene);
-        this.scene = scene;
+        this.diagramScene = scene;
         this.slot = slot;
         figureWidget = fw;
-        this.setToolTipText("<HTML>" + slot.getName() + "</HTML>");
+        this.setToolTipText("<HTML>" + slot.getToolTipText() + "</HTML>");
         this.setCheckClipping(true);
-    }
-
-    public Point getAnchorPosition() {
-        Point p = new Point(figureWidget.getFigure().getPosition());
-        Point p2 = slot.getRelativePosition();
-        p.translate(p2.x, p2.y);
-        return p;
+        parent.addChild(this);
+        
+        //this.setPreferredBounds(this.calculateClientArea());
     }
-
-    protected void init() {
-
-        Point p = calculateRelativeLocation();
-        Rectangle r = calculateClientArea();
-        p = new Point(p.x, p.y - r.height / 2);
-        this.setPreferredLocation(p);
+    
+    
+    @Override
+    protected void notifyStateChanged(ObjectState previousState, ObjectState state) {
+        super.notifyStateChanged(previousState, state);
+	repaint();
     }
-
+    
     public Slot getSlot() {
         return slot;
     }
@@ -84,43 +83,96 @@
     @Override
     protected void paintWidget() {
 
-        if (scene.getRealZoomFactor() < ZOOM_FACTOR) {
+        if (getScene().getZoomFactor() < ZOOM_FACTOR) {
             return;
         }
 
-        if (bufferImage == null) {
-            Graphics2D g = this.getGraphics();
-            g.setColor(Color.DARK_GRAY);
-            int w = this.getBounds().width;
-            int h = this.getBounds().height;
+        Graphics2D g = this.getGraphics();
+       // g.setColor(Color.DARK_GRAY);
+        int w = this.getBounds().width;
+        int h = this.getBounds().height;
+
+        if(getSlot().getSource().getSourceNodes().size() > 0) {
+            final int SMALLER = 0;
+            g.setColor(getSlot().getColor());
 
-            if (getSlot().getShortName() != null && getSlot().getShortName().length() > 0 && scene.getRealZoomFactor() >= TEXT_ZOOM_FACTOR) {
-                Font f = new Font("Arial", Font.PLAIN, 8);
-                g.setFont(f.deriveFont(7.5f));
+            int FONT_OFFSET = 2;
+            
+            int s = h - SMALLER;
+            int rectW = s;
+            
+            Font font = this.getSlot().getFigure().getDiagram().getSlotFont();
+            if(this.getState().isSelected()) {
+                font = font.deriveFont(Font.BOLD);
+            }
+            
+            if (getSlot().getShortName() != null && getSlot().getShortName().length() > 0) {
+                g.setFont(font);
                 Rectangle2D r1 = g.getFontMetrics().getStringBounds(getSlot().getShortName(), g);
-                g.drawString(getSlot().getShortName(), (int) (this.getBounds().width - r1.getWidth()) / 2, (int) (this.getBounds().height + r1.getHeight()) / 2);
+                rectW = (int)r1.getWidth() + FONT_OFFSET * 2;
+            }
+            g.fillRect(w/2 - rectW/2, 0, rectW-1, s-1);
+            
+            if(this.getState().isHighlighted()) {
+                g.setColor(Color.BLUE);
             } else {
+                g.setColor(Color.BLACK);
+            }
+            g.drawRect(w/2 - rectW/2, 0, rectW-1, s-1);
+            
+            
+            if (getSlot().getShortName() != null && getSlot().getShortName().length() > 0 && getScene().getZoomFactor() >= TEXT_ZOOM_FACTOR) {
+                Rectangle2D r1 = g.getFontMetrics().getStringBounds(getSlot().getShortName(), g);
+                g.drawString(getSlot().getShortName(), (int) (w - r1.getWidth()) / 2, g.getFontMetrics().getAscent()-1);//(int) (r1.getHeight()));
+            }
+            
+        } else {
 
-                if (slot instanceof OutputSlot) {
-                    g.fillArc(w / 4, -h / 4 - 1, w / 2, h / 2, 180, 180);
-                } else {
-                    g.fillArc(w / 4, 3 * h / 4, w / 2, h / 2, 0, 180);
-                }
+            if(this.getState().isHighlighted()) {
+                g.setColor(Color.BLUE);
+            } else {
+                g.setColor(Color.BLACK);
+            }
+            int r = 2;
+            if (slot instanceof OutputSlot) {
+                g.fillOval(w/2-r, Figure.SLOT_WIDTH - Figure.SLOT_START - r, 2*r, 2*r);
+                //g.fillArc(w / 2 - r, -r, 2*r, 2*r, 180, 180);
+            } else {
+                g.fillOval(w/2-r, Figure.SLOT_START - r, 2*r, 2*r);
+                //g.fillArc(w / 2 - r, h - r, 2*r, 2*r, 0, 180);
             }
         }
     }
 
     @Override
     protected Rectangle calculateClientArea() {
-        return new Rectangle(0, 0, Figure.SLOT_WIDTH, Figure.SLOT_WIDTH);
+        return new Rectangle(0, 0, slot.getWidth(), Figure.SLOT_WIDTH);
+    }
+ 
+    protected abstract int calculateSlotWidth();
+    
+    protected int calculateWidth(int count) {
+        return getFigureWidget().getFigure().getWidth() / count;
     }
 
-    protected abstract Point calculateRelativeLocation();
+    public void handleDoubleClick(Widget w, WidgetAction.WidgetMouseEvent e) {
+        Set<Integer> hiddenNodes = new HashSet<Integer>(diagramScene.getModel().getHiddenNodes());
+        if (diagramScene.isAllVisible()) {
+            hiddenNodes = new HashSet<Integer>(diagramScene.getModel().getGraphToView().getGroup().getAllNodes());
+        } 
 
-    protected double calculateRelativeY(int size, int index) {
-        assert index >= 0 && index < size;
-        assert size > 0;
-        double height = getFigureWidget().getBounds().getHeight();
-        return height * (index + 1) / (size + 1);
+        boolean progress = false;
+        for(Figure f : diagramScene.getModel().getDiagramToView().getFigures()) {
+            for(Slot s : f.getSlots()) {
+                if(DiagramScene.doesIntersect(s.getSource().getSourceNodesAsSet(), slot.getSource().getSourceNodesAsSet())) {
+                    progress = true;
+                    hiddenNodes.removeAll(f.getSource().getSourceNodesAsSet());
+                }
+            }
+        }
+
+        if(progress) {
+            this.diagramScene.getModel().showNot(hiddenNodes);
+        }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/branding.jnlp	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE jnlp PUBLIC "-//Sun Microsystems, Inc//DTD JNLP Discriptor 1.5//EN" "http://java.sun.com/dtd/JNLP-1.5.dtd">
+<jnlp spec="1.0+" codebase="$$codebase">
+  <information>
+      <title>${app.title}</title>
+      <vendor>${app.title} vendor</vendor>
+      <description>${app.name} application</description>
+      <icon href="${app.icon}"/>
+  </information>
+  ${jnlp.permissions}
+  <resources>
+    ${jnlp.branding.jars}
+  </resources>
+  <component-desc/>
+</jnlp>  
--- a/src/share/tools/IdealGraphVisualizer/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -1,7 +1,7 @@
 currentVersion=IdealGraphVisualizer {0}
 LBL_splash_window_title=Starting IdealGraphVisualizer
 SPLASH_WIDTH=475
-SplashProgressBarBounds=0,268,473,6
+SplashProgressBarBounds=0,273,475,6
 SplashProgressBarColor=0xFFFFFF
-SplashRunningTextBounds=269,253,205,12
+SplashRunningTextBounds=10,283,460,12
 SplashRunningTextColor=0xFFFFFF
Binary file src/share/tools/IdealGraphVisualizer/branding/core/core.jar/org/netbeans/core/startup/frame.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/branding/core/core.jar/org/netbeans/core/startup/frame32.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/branding/core/core.jar/org/netbeans/core/startup/frame48.gif has changed
Binary file src/share/tools/IdealGraphVisualizer/branding/core/core.jar/org/netbeans/core/startup/splash.gif has changed
--- a/src/share/tools/IdealGraphVisualizer/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -1,2 +1,2 @@
-CTL_MainWindow_Title=IdealGraphVisualizer {0}
-CTL_MainWindow_Title_No_Project=IdealGraphVisualizer {0}
+CTL_MainWindow_Title=IdealGraphVisualizer
+CTL_MainWindow_Title_No_Project=IdealGraphVisualizer
--- a/src/share/tools/IdealGraphVisualizer/build.xml	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/build.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -5,4 +5,12 @@
 <project name="IdealGraphVisualizer" basedir=".">
     <description>Builds the module suite IdealGraphVisualizer.</description>
     <import file="nbproject/build-impl.xml"/>
+    
+    <target name="build-launchers" depends="suite.build-launchers">
+        <!-- Drop memory presets (-Xms, -Xmx) from default_options of packaged builds and let the executing VM choose reasonable defaults -->
+        <replaceregexp file="${build.launcher.dir}/etc/${app.name}.conf" byline="true" match="^default_options=.*" replace='default_options="--branding idealgraphvisualizer"' />
+    </target>
+    
+    <!-- Local (environment-specific) extensions/modifications to the build -->
+    <import file="build-local.xml" optional="true" />
 </project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/master.jnlp	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE jnlp PUBLIC "-//Sun Microsystems, Inc//DTD JNLP Discriptor 1.5//EN" "http://java.sun.com/dtd/JNLP-1.5.dtd">
+<jnlp spec="1.0+" codebase="$$codebase">
+  <information>
+      <title>${app.title}</title>
+      <vendor>${app.title} vendor</vendor>
+      <description>${app.name} application</description>
+      <icon href="${app.icon}"/>
+  </information>
+  <security><all-permissions/></security>
+  <resources>
+    <!-- The following property is needed when running with unsigned jars: -->
+    <property name="netbeans.jnlp.fixPolicy" value="${netbeans.jnlp.fixPolicy}"/>
+    <extension name='branding' href='branding.jnlp' />
+<!-- The following line will be replaced with an automatically generated list of resources: -->
+<!--${jnlp.resources}-->
+  </resources>
+  <resources os="Mac OS X">
+      <property name="netbeans.user" value="${user.home}/Library/Application Support/${app.name}"/>
+  </resources>
+  <application-desc>
+    <argument>--branding</argument>
+    <argument>${branding.token}</argument>
+  </application-desc>
+</jnlp>  
--- a/src/share/tools/IdealGraphVisualizer/nbproject/build-impl.xml	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/nbproject/build-impl.xml	Wed Jul 27 17:32:44 2011 -0700
@@ -4,6 +4,13 @@
 ***         EDIT ../build.xml INSTEAD         ***
 -->
 <project name="IdealGraphVisualizer-impl" basedir=".." xmlns:sproject="http://www.netbeans.org/ns/nb-module-suite-project/1">
+    <fail message="Please build using Ant 1.7.1 or higher.">
+        <condition>
+            <not>
+                <antversion atleast="1.7.1"/>
+            </not>
+        </condition>
+    </fail>
     <property file="nbproject/private/platform-private.properties"/>
     <property file="nbproject/platform.properties"/>
     <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-suite-project/1">
@@ -13,13 +20,28 @@
             <property name="@{name}" value="${@{value}}"/>
         </sequential>
     </macrodef>
+    <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-suite-project/1">
+        <attribute name="property"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{property}" value="@{value}"/>
+        </sequential>
+    </macrodef>
     <property file="${user.properties.file}"/>
     <sproject:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir"/>
-    <sproject:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir"/>
-    <fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'">
+    <sproject:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir"/>
+    <sproject:evalprops property="cluster.path.evaluated" value="${cluster.path}"/>
+    <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
         <condition>
             <not>
-                <available file="${harness.dir}" type="dir"/>
+                <contains string="${cluster.path.evaluated}" substring="platform"/>
+            </not>
+        </condition>
+    </fail>
+    <fail message="Cannot find NetBeans build harness. ${line.separator}Check that nbplatform.${nbplatform.active}.netbeans.dest.dir and nbplatform.${nbplatform.active}.harness.dir are defined. ${line.separator}On a developer machine these are normally defined in ${user.properties.file}=${netbeans.user}/build.properties ${line.separator}but for automated builds you should pass these properties to Ant explicitly.">
+        <condition>
+            <not>
+                <available type="dir" file="${harness.dir}"/>
             </not>
         </condition>
     </fail>
--- a/src/share/tools/IdealGraphVisualizer/nbproject/genfiles.properties	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/nbproject/genfiles.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -1,8 +1,8 @@
-build.xml.data.CRC32=72833581
-build.xml.script.CRC32=e9c757c5
-build.xml.stylesheet.CRC32=531c622b
+build.xml.data.CRC32=3c2c6126
+build.xml.script.CRC32=48934e60
+build.xml.stylesheet.CRC32=eaf9f76a@1.45.1
 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
 # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
-nbproject/build-impl.xml.data.CRC32=72833581
-nbproject/build-impl.xml.script.CRC32=1b6f3648
-nbproject/build-impl.xml.stylesheet.CRC32=196c7090
+nbproject/build-impl.xml.data.CRC32=3c2c6126
+nbproject/build-impl.xml.script.CRC32=5a29eb53
+nbproject/build-impl.xml.stylesheet.CRC32=183e6ef3@1.45.1
--- a/src/share/tools/IdealGraphVisualizer/nbproject/platform.properties	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/nbproject/platform.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -1,29 +1,168 @@
-# Deprecated since 5.0u1; for compatibility with 5.0:
-disabled.clusters=\
-    apisupport1,\
-    gsf1,\
-    harness,\
-    ide9,\
-    java2,\
-    nb6.1,\
-    profiler3
+cluster.path=\
+    ${nbplatform.active.dir}/ide:\
+    ${nbplatform.active.dir}/platform
 disabled.modules=\
+    org.apache.xml.resolver,\
+    org.mozilla.rhino.patched,\
+    org.netbeans.api.debugger,\
+    org.netbeans.api.java.classpath,\
+    org.netbeans.api.xml,\
+    org.netbeans.core.browser,\
     org.netbeans.core.execution,\
+    org.netbeans.core.ide,\
     org.netbeans.core.multiview,\
-    org.netbeans.core.output2,\
+    org.netbeans.lib.cvsclient,\
+    org.netbeans.lib.terminalemulator,\
+    org.netbeans.libs.antlr3.runtime,\
+    org.netbeans.libs.bugtracking,\
+    org.netbeans.libs.bugzilla,\
+    org.netbeans.libs.bytelist,\
+    org.netbeans.libs.commons_codec,\
+    org.netbeans.libs.commons_logging,\
+    org.netbeans.libs.commons_net,\
+    org.netbeans.libs.freemarker,\
+    org.netbeans.libs.ini4j,\
+    org.netbeans.libs.jakarta_oro,\
+    org.netbeans.libs.jaxb,\
+    org.netbeans.libs.jsch,\
+    org.netbeans.libs.jsr223,\
+    org.netbeans.libs.jvyamlb,\
+    org.netbeans.libs.jzlib,\
+    org.netbeans.libs.lucene,\
+    org.netbeans.libs.smack,\
+    org.netbeans.libs.svnClientAdapter,\
+    org.netbeans.libs.svnClientAdapter.javahl,\
+    org.netbeans.libs.svnClientAdapter.svnkit,\
+    org.netbeans.libs.swingx,\
+    org.netbeans.libs.xerces,\
     org.netbeans.modules.autoupdate.services,\
     org.netbeans.modules.autoupdate.ui,\
+    org.netbeans.modules.bugtracking,\
+    org.netbeans.modules.bugtracking.bridge,\
+    org.netbeans.modules.bugzilla,\
     org.netbeans.modules.core.kit,\
+    org.netbeans.modules.csl.api,\
+    org.netbeans.modules.css.editor,\
+    org.netbeans.modules.css.visual,\
+    org.netbeans.modules.db,\
+    org.netbeans.modules.db.core,\
+    org.netbeans.modules.db.dataview,\
+    org.netbeans.modules.db.drivers,\
+    org.netbeans.modules.db.kit,\
+    org.netbeans.modules.db.metadata.model,\
+    org.netbeans.modules.db.mysql,\
+    org.netbeans.modules.db.sql.editor,\
+    org.netbeans.modules.db.sql.visualeditor,\
+    org.netbeans.modules.dbapi,\
+    org.netbeans.modules.defaults,\
+    org.netbeans.modules.derby,\
+    org.netbeans.modules.dlight.nativeexecution,\
+    org.netbeans.modules.dlight.terminal,\
+    org.netbeans.modules.editor.bookmarks,\
+    org.netbeans.modules.editor.bracesmatching,\
+    org.netbeans.modules.editor.codetemplates,\
+    org.netbeans.modules.editor.completion,\
+    org.netbeans.modules.editor.guards,\
+    org.netbeans.modules.editor.indent.project,\
+    org.netbeans.modules.editor.kit,\
+    org.netbeans.modules.editor.macros,\
+    org.netbeans.modules.editor.structure,\
+    org.netbeans.modules.extbrowser,\
+    org.netbeans.modules.extexecution,\
+    org.netbeans.modules.extexecution.destroy,\
     org.netbeans.modules.favorites,\
-    org.netbeans.modules.javahelp,\
-    org.netbeans.modules.masterfs,\
-    org.netbeans.modules.options.keymap,\
-    org.netbeans.modules.sendopts,\
-    org.netbeans.modules.templates,\
+    org.netbeans.modules.glassfish.common,\
+    org.netbeans.modules.gototest,\
+    org.netbeans.modules.gsf.codecoverage,\
+    org.netbeans.modules.gsf.testrunner,\
+    org.netbeans.modules.html,\
+    org.netbeans.modules.html.editor,\
+    org.netbeans.modules.html.editor.lib,\
+    org.netbeans.modules.html.lexer,\
+    org.netbeans.modules.html.parser,\
+    org.netbeans.modules.html.validation,\
+    org.netbeans.modules.httpserver,\
+    org.netbeans.modules.hudson,\
+    org.netbeans.modules.hudson.mercurial,\
+    org.netbeans.modules.hudson.subversion,\
+    org.netbeans.modules.ide.kit,\
+    org.netbeans.modules.image,\
+    org.netbeans.modules.javascript.editing,\
+    org.netbeans.modules.javascript.hints,\
+    org.netbeans.modules.javascript.kit,\
+    org.netbeans.modules.javascript.refactoring,\
+    org.netbeans.modules.jellytools.ide,\
+    org.netbeans.modules.jumpto,\
+    org.netbeans.modules.languages,\
+    org.netbeans.modules.languages.diff,\
+    org.netbeans.modules.languages.manifest,\
+    org.netbeans.modules.languages.yaml,\
+    org.netbeans.modules.lexer.nbbridge,\
+    org.netbeans.modules.localhistory,\
+    org.netbeans.modules.mercurial,\
+    org.netbeans.modules.parsing.api,\
+    org.netbeans.modules.parsing.lucene,\
+    org.netbeans.modules.print.editor,\
+    org.netbeans.modules.project.ant,\
+    org.netbeans.modules.project.libraries,\
+    org.netbeans.modules.projectui,\
+    org.netbeans.modules.projectui.buildmenu,\
+    org.netbeans.modules.projectuiapi,\
+    org.netbeans.modules.properties,\
+    org.netbeans.modules.properties.syntax,\
+    org.netbeans.modules.refactoring.api,\
+    org.netbeans.modules.schema2beans,\
+    org.netbeans.modules.server,\
+    org.netbeans.modules.servletapi,\
+    org.netbeans.modules.spellchecker,\
+    org.netbeans.modules.spellchecker.apimodule,\
+    org.netbeans.modules.spellchecker.bindings.htmlxml,\
+    org.netbeans.modules.spellchecker.bindings.properties,\
+    org.netbeans.modules.spellchecker.dictionary_en,\
+    org.netbeans.modules.spellchecker.kit,\
+    org.netbeans.modules.subversion,\
+    org.netbeans.modules.swing.validation,\
+    org.netbeans.modules.target.iterator,\
+    org.netbeans.modules.tasklist.kit,\
+    org.netbeans.modules.tasklist.projectint,\
+    org.netbeans.modules.tasklist.todo,\
+    org.netbeans.modules.tasklist.ui,\
+    org.netbeans.modules.terminal,\
+    org.netbeans.modules.usersguide,\
+    org.netbeans.modules.utilities,\
+    org.netbeans.modules.utilities.project,\
+    org.netbeans.modules.versioning,\
+    org.netbeans.modules.versioning.indexingbridge,\
+    org.netbeans.modules.versioning.system.cvss,\
+    org.netbeans.modules.versioning.util,\
+    org.netbeans.modules.web.client.tools.api,\
+    org.netbeans.modules.web.common,\
+    org.netbeans.modules.xml,\
+    org.netbeans.modules.xml.axi,\
+    org.netbeans.modules.xml.catalog,\
+    org.netbeans.modules.xml.core,\
+    org.netbeans.modules.xml.jaxb.api,\
+    org.netbeans.modules.xml.lexer,\
+    org.netbeans.modules.xml.multiview,\
+    org.netbeans.modules.xml.retriever,\
+    org.netbeans.modules.xml.schema.completion,\
+    org.netbeans.modules.xml.schema.model,\
+    org.netbeans.modules.xml.tax,\
+    org.netbeans.modules.xml.text,\
+    org.netbeans.modules.xml.tools,\
+    org.netbeans.modules.xml.wsdl.model,\
+    org.netbeans.modules.xml.xam,\
+    org.netbeans.modules.xml.xdm,\
+    org.netbeans.modules.xsl,\
+    org.netbeans.spi.debugger.ui,\
+    org.netbeans.spi.editor.hints,\
+    org.netbeans.spi.navigator,\
+    org.netbeans.spi.palette,\
+    org.netbeans.spi.tasklist,\
+    org.netbeans.spi.viewmodel,\
+    org.netbeans.swing.dirchooser,\
     org.openide.compat,\
     org.openide.execution,\
+    org.openide.options,\
     org.openide.util.enumerations
-enabled.clusters=\
-    platform8
-nbjdk.active=default
 nbplatform.active=default
--- a/src/share/tools/IdealGraphVisualizer/nbproject/project.properties	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/IdealGraphVisualizer/nbproject/project.properties	Wed Jul 27 17:32:44 2011 -0700
@@ -15,10 +15,18 @@
     ${project.com.sun.hotspot.igv.difference}:\
     ${project.com.sun.hotspot.igv.settings}:\
     ${project.com.sun.hotspot.igv.util}:\
+    ${project.com.sun.hotspot.igv.rhino}:\
     ${project.com.sun.hotspot.igv.svg}:\
     ${project.com.sun.hotspot.connection}:\
     ${project.com.sun.hotspot.igv.servercompilerscheduler}:\
-    ${project.com.sun.hotspot.igv.filterwindow}
+    ${project.com.sun.hotspot.igv.filterwindow}:\
+    ${project.com.sun.hotspot.igv.graphtotext}:\
+    ${project.com.sun.hotspot.igv.java6scriptingproxy}:\
+    ${project.com.sun.hotspot.igv.graphtexteditor}:\
+    ${project.com.sun.hotspot.igv.structuredtext}:\
+    ${project.com.sun.hotspot.igv.texteditor}:\
+    ${project.com.sun.hotspot.igv.selectioncoordinator}:\
+    ${project.com.sun.hotspot.igv.graal}
 project.com.sun.hotspot.connection=NetworkConnection
 project.com.sun.hotspot.igv.bytecodes=Bytecodes
 project.com.sun.hotspot.igv.controlflow=ControlFlow
@@ -27,13 +35,24 @@
 project.com.sun.hotspot.igv.difference=Difference
 project.com.sun.hotspot.igv.filter=Filter
 project.com.sun.hotspot.igv.filterwindow=FilterWindow
+project.com.sun.hotspot.igv.graal=Graal
 project.com.sun.hotspot.igv.graph=Graph
+project.com.sun.hotspot.igv.graphtexteditor=GraphTextEditor
+project.com.sun.hotspot.igv.graphtotext=GraphToText
 project.com.sun.hotspot.igv.hierarchicallayout=HierarchicalLayout
+project.com.sun.hotspot.igv.java6scriptingproxy=Java6ScriptingProxy
 project.com.sun.hotspot.igv.layout=Layout
+project.com.sun.hotspot.igv.rhino=RhinoScriptEngineProxy
+project.com.sun.hotspot.igv.selectioncoordinator=SelectionCoordinator
 project.com.sun.hotspot.igv.servercompilerscheduler=ServerCompiler
 project.com.sun.hotspot.igv.settings=Settings
+project.com.sun.hotspot.igv.structuredtext=StructuredText
 project.com.sun.hotspot.igv.svg=BatikSVGProxy
+project.com.sun.hotspot.igv.texteditor=TextEditor
 project.com.sun.hotspot.igv.view=View
 project.com.sun.hotspot.igv.util=Util
-run.args = -J-server -J-Xms64m -J-Xmx1g -J-da
-run.args.extra = -J-server -J-Xms64m -J-Xmx1g -J-da
+
+# Disable assertions for RequestProcessor to prevent annoying messages in case
+# of multiple SceneAnimator update tasks in the default RequestProcessor.
+run.args.extra = -J-client -J-da:org.openide.util.RequestProcessor
+debug.args.extra = -J-client -J-da:org.openide.util.RequestProcessor
--- a/src/share/tools/ProjectCreator/BuildConfig.java	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/tools/ProjectCreator/BuildConfig.java	Wed Jul 27 17:32:44 2011 -0700
@@ -63,7 +63,20 @@
         // ones mentioned above were needed to expand format
         String buildBase = expandFormat(getFieldString(null, "BuildBase"));
         String sourceBase = getFieldString(null, "SourceBase");
-        String outDir = buildBase;
+        String outDir = sourceBase + Util.sep + "java";
+	if (!platformName.equals("Win32")) {
+		outDir += "64";
+	}
+	if (!build.equals("product")) {
+		outDir += Util.sep + "fastdebug";
+	}
+	outDir += Util.sep + "jre" + Util.sep + "bin";
+	if (flavour.equals("compiler1")) {
+		outDir += Util.sep + "client";
+	} else {
+		outDir += Util.sep + "server";
+	}
+	buildBase = outDir;
 
         put("Id", flavourBuild);
         put("OutputDir", outDir);
@@ -239,7 +252,19 @@
 
     void initDefaultDefines(Vector defines) {
         Vector sysDefines = new Vector();
-        sysDefines.add("WIN32");
+
+        if( vars.get("PlatformName").equals("Win32")) {
+            sysDefines.add("WIN32");
+        } else {
+            sysDefines.add("_AMD64_");
+            sysDefines.add("AMD64");
+            sysDefines.add("_WIN64");
+            sysDefines.add("_LP64");
+            if (System.getenv("MSC_VER") != null)
+               sysDefines.add("MSC_VER=" + System.getenv("MSC_VER"));
+            sysDefines.add("HOTSPOT_LIB_ARCH=\\\"amd64\\\"");
+        }
+	
         sysDefines.add("_WINDOWS");
         sysDefines.add("HOTSPOT_BUILD_USER=\\\""+System.getProperty("user.name")+"\\\"");
         sysDefines.add("HOTSPOT_BUILD_TARGET=\\\""+get("Build")+"\\\"");
@@ -314,6 +339,10 @@
         return get("Build");
     }
 
+    String outputDir() {
+        return get("OutputDir");
+    }
+
     Object getSpecificField(String field) {
         return getField(get("Id"), field);
     }
@@ -502,6 +531,9 @@
                 case 'f':
                     sb.append(flavour());
                     break;
+		case 'o':
+		    sb.append(outputDir());
+		    break;
                 default:
                     sb.append(ch);
                     sb.append(ch1);
--- a/src/share/vm/c1/c1_Compiler.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/c1/c1_Compiler.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -90,6 +90,7 @@
 
 
 void Compiler::compile_method(ciEnv* env, ciMethod* method, int entry_bci) {
+  assert(!UseGraal, "c1 called in UseGraal mode!");
   // Allocate buffer blob once at startup since allocation for each
   // compilation seems to be too expensive (at least on Intel win32).
   BufferBlob* buffer_blob = CompilerThread::current()->get_buffer_blob();
--- a/src/share/vm/c1/c1_IR.hpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/c1/c1_IR.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -237,7 +237,7 @@
     // reexecute allowed only for the topmost frame
     bool reexecute = topmost ? should_reexecute() : false;
     bool return_oop = false; // This flag will be ignored since it used only for C2 with escape analysis.
-    recorder->describe_scope(pc_offset, scope()->method(), bci(), reexecute, is_method_handle_invoke, return_oop, locvals, expvals, monvals);
+    recorder->describe_scope(pc_offset, scope()->method(), bci(), reexecute, false, is_method_handle_invoke, return_oop, locvals, expvals, monvals);
   }
 };
 
--- a/src/share/vm/c1/c1_LIRAssembler.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/c1/c1_LIRAssembler.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -405,7 +405,7 @@
     if (s == NULL)  break;
     IRScope* scope = s->scope();
     //Always pass false for reexecute since these ScopeDescs are never used for deopt
-    debug_info->describe_scope(pc_offset, scope->method(), s->bci(), false/*reexecute*/);
+    debug_info->describe_scope(pc_offset, scope->method(), s->bci(), false/*reexecute*/, false/*rethrow_exception*/);
   }
 
   debug_info->end_non_safepoint(pc_offset);
--- a/src/share/vm/c1/c1_LIRGenerator.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/c1/c1_LIRGenerator.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -2799,7 +2799,7 @@
 
       // Load CallSite object from constant pool cache.
       __ oop2reg(cpcache->constant_encoding(), tmp);
-      __ move_wide(new LIR_Address(tmp, call_site_offset, T_OBJECT), tmp);
+      __ move_wide(new LIR_Address(tmp, (int)call_site_offset, T_OBJECT), tmp);
 
       // Load target MethodHandle from CallSite object.
       __ load(new LIR_Address(tmp, java_lang_invoke_CallSite::target_offset_in_bytes(), T_OBJECT), receiver);
--- a/src/share/vm/c1/c1_Runtime1.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/c1/c1_Runtime1.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -201,8 +201,15 @@
     case slow_subtype_check_id:
     case fpu2long_stub_id:
     case unwind_exception_id:
-    case counter_overflow_id:
-#if defined(SPARC) || defined(PPC)
+    case graal_verify_pointer_id:
+    case graal_unwind_exception_call_id:
+    case graal_slow_subtype_check_id:
+    case graal_arithmetic_frem_id:
+    case graal_arithmetic_drem_id:
+#ifndef TIERED
+    case counter_overflow_id: // Not generated outside the tiered world
+#endif
+#ifdef SPARC
     case handle_exception_nofpu_id:  // Unused on sparc
 #endif
       break;
@@ -460,6 +467,9 @@
   thread->set_is_method_handle_return(false);
 
   Handle exception(thread, ex);
+  if (UseGraal && exception.is_null()) {
+    exception = Exceptions::new_exception(thread, vmSymbols::java_lang_NullPointerException(), NULL);
+  }
   nm = CodeCache::find_nmethod(pc);
   assert(nm != NULL, "this is not an nmethod");
   // Adjust the pc as needed/
@@ -649,12 +659,22 @@
 
 JRT_ENTRY_NO_ASYNC(void, Runtime1::monitorenter(JavaThread* thread, oopDesc* obj, BasicObjectLock* lock))
   NOT_PRODUCT(_monitorenter_slowcase_cnt++;)
+#ifdef ASSERT
+  if (TraceGraal >= 3) {
+    tty->print_cr("entered locking slow case with obj=" INTPTR_FORMAT " and lock= " INTPTR_FORMAT, obj, lock);
+  }
   if (PrintBiasedLockingStatistics) {
     Atomic::inc(BiasedLocking::slow_path_entry_count_addr());
   }
+#endif
   Handle h_obj(thread, obj);
   assert(h_obj()->is_oop(), "must be NULL or an object");
   if (UseBiasedLocking) {
+    if (UseFastLocking) {
+      assert(obj == lock->obj(), "must match");
+    } else {
+      lock->set_obj(obj);
+    }
     // Retry fast entry if bias is revoked to avoid unnecessary inflation
     ObjectSynchronizer::fast_enter(h_obj, lock->lock(), true, CHECK);
   } else {
@@ -667,6 +687,14 @@
       ObjectSynchronizer::fast_enter(h_obj, lock->lock(), false, THREAD);
     }
   }
+#ifdef ASSERT
+  if (TraceGraal >= 3) {
+    tty->print_cr("exiting locking lock state: obj=" INTPTR_FORMAT, lock->obj());
+    lock->lock()->print_on(tty);
+    tty->print_cr("");
+    tty->print_cr("done");
+  }
+#endif
 JRT_END
 
 
@@ -678,7 +706,19 @@
   EXCEPTION_MARK;
 
   oop obj = lock->obj();
-  assert(obj->is_oop(), "must be NULL or an object");
+
+#ifdef DEBUG
+  if (!obj->is_oop()) {
+    ResetNoHandleMark rhm;
+    nmethod* method = thread->last_frame().cb()->as_nmethod_or_null();
+    if (method != NULL) {
+      tty->print_cr("ERROR in monitorexit in method %s wrong obj " INTPTR_FORMAT, method->name(), obj);
+    }
+    thread->print_stack_on(tty);
+    assert(false, "invalid lock object pointer dected");
+  }
+#endif
+
   if (UseFastLocking) {
     // When using fast locking, the compiled code has already tried the fast case
     ObjectSynchronizer::slow_exit(obj, lock->lock(), THREAD);
@@ -874,7 +914,9 @@
           assert(k != NULL && !k->is_klass(), "must be class mirror or other Java constant");
         }
         break;
-      default: Unimplemented();
+      default:
+        tty->print_cr("Unhandled bytecode: %d stub_id=%d caller=%s bci=%d pc=%d", code, stub_id, caller_method->name()->as_C_string(), bci, caller_frame.pc());
+        Unimplemented();
     }
     // convert to handle
     load_klass = Handle(THREAD, k);
--- a/src/share/vm/c1/c1_Runtime1.hpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/c1/c1_Runtime1.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -70,6 +70,14 @@
   stub(g1_post_barrier_slow)         \
   stub(fpu2long_stub)                \
   stub(counter_overflow)             \
+  stub(graal_unwind_exception_call)    \
+  stub(graal_handle_exception)         \
+  stub(graal_slow_subtype_check)       \
+  stub(graal_arithmetic_frem)          \
+  stub(graal_arithmetic_drem)          \
+  stub(graal_monitorenter)             \
+  stub(graal_monitorexit)              \
+  stub(graal_verify_pointer)           \
   last_entry(number_of_ids)
 
 #define DECLARE_STUB_ID(x)       x ## _id ,
@@ -125,6 +133,7 @@
   static OopMapSet* generate_exception_throw(StubAssembler* sasm, address target, bool has_argument);
   static OopMapSet* generate_handle_exception(StubID id, StubAssembler* sasm);
   static void       generate_unwind_exception(StubAssembler *sasm);
+  static void       graal_generate_handle_exception(StubAssembler *sasm, OopMapSet* oop_maps, OopMap* oop_map);
   static OopMapSet* generate_patching(StubAssembler* sasm, address target);
 
   static OopMapSet* generate_stub_call(StubAssembler* sasm, Register result, address entry,
--- a/src/share/vm/c1/c1_globals.hpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/c1/c1_globals.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -53,6 +53,16 @@
 //
 #define C1_FLAGS(develop, develop_pd, product, product_pd, notproduct)      \
                                                                             \
+  product(bool, UseGraal, false,                                              \
+          "Use graal instead of C1")                                          \
+  product(bool, GraalBailoutIsFatal, true,                                    \
+          "Abort the VM on graal bailout")                                    \
+  product(bool, BootstrapGraal, false,                                        \
+          "Bootstrap graal before running Java main method")                  \
+  product(intx, TraceGraal, 0,                                                \
+          "Trace level for graal")                                            \
+  product(bool, TraceSignals, false,                                        \
+          "Trace signals and implicit exception handling")                  \
   /* Printing */                                                            \
   notproduct(bool, PrintC1Statistics, false,                                \
           "Print Compiler1 statistics" )                                    \
@@ -233,7 +243,7 @@
   develop(bool, UseFastNewObjectArray, true,                                \
           "Use fast inlined object array allocation")                       \
                                                                             \
-  develop(bool, UseFastLocking, true,                                       \
+  product(bool, UseFastLocking, true,                                       \
           "Use fast inlined locking code")                                  \
                                                                             \
   develop(bool, UseSlowPath, false,                                         \
@@ -278,7 +288,7 @@
   product(intx, CompilationRepeat, 0,                                       \
           "Number of times to recompile method before returning result")    \
                                                                             \
-  develop(intx, NMethodSizeLimit, (32*K)*wordSize,                          \
+  develop(intx, NMethodSizeLimit, (64*K)*wordSize,                          \
           "Maximum size of a compiled method.")                             \
                                                                             \
   develop(bool, TraceFPUStack, false,                                       \
--- a/src/share/vm/ci/ciCallProfile.hpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/ci/ciCallProfile.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -61,6 +61,7 @@
   // Note:  The following predicates return false for invalid profiles:
   bool      has_receiver(int i) const { return _limit > i; }
   int       morphism() const          { return _morphism; }
+  int       limit() const             { return _limit; }
 
   int       count() const             { return _count; }
   int       receiver_count(int i)  {
--- a/src/share/vm/ci/ciEnv.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/ci/ciEnv.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -201,6 +201,7 @@
 }
 
 ciEnv::~ciEnv() {
+  _factory->cleanup();
   CompilerThread* current_thread = CompilerThread::current();
   _factory->remove_symbols();
   current_thread->set_env(NULL);
--- a/src/share/vm/ci/ciEnv.hpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/ci/ciEnv.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -105,6 +105,8 @@
   ciInstance* _the_null_string;      // The Java string "null"
   ciInstance* _the_min_jint_string; // The Java string "-2147483648"
 
+public:
+
   // Look up a klass by name from a particular class loader (the accessor's).
   // If require_local, result must be defined in that class loader, or NULL.
   // If !require_local, a result from remote class loader may be reported,
@@ -135,6 +137,8 @@
                                  int method_index, Bytecodes::Code bc,
                                  ciInstanceKlass* loading_klass);
 
+private:
+
   // Implementation methods for loading and constant pool access.
   ciKlass* get_klass_by_name_impl(ciKlass* accessing_klass,
                                   constantPoolHandle cpool,
@@ -164,6 +168,7 @@
                            Symbol*         sig,
                            Bytecodes::Code bc);
 
+  public:
   // Get a ciObject from the object factory.  Ensures uniqueness
   // of ciObjects.
   ciObject* get_object(oop o) {
@@ -173,6 +178,7 @@
       return _factory->get(o);
     }
   }
+  private:
 
   ciSymbol* get_symbol(Symbol* o) {
     if (o == NULL) {
--- a/src/share/vm/ci/ciField.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/ci/ciField.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -306,15 +306,20 @@
   return type;
 }
 
+bool ciField::will_link(ciInstanceKlass* accessing_klass,
+                        Bytecodes::Code bc) {
+  VM_ENTRY_MARK;
+  return will_link_from_vm(accessing_klass, bc);
+}
 
 // ------------------------------------------------------------------
 // ciField::will_link
 //
 // Can a specific access to this field be made without causing
 // link errors?
-bool ciField::will_link(ciInstanceKlass* accessing_klass,
+bool ciField::will_link_from_vm(ciInstanceKlass* accessing_klass,
                         Bytecodes::Code bc) {
-  VM_ENTRY_MARK;
+  Thread* THREAD = Thread::current();
   if (_offset == -1) {
     // at creation we couldn't link to our holder so we need to
     // maintain that stance, otherwise there's no safe way to use this
--- a/src/share/vm/ci/ciField.hpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/ci/ciField.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -168,6 +168,8 @@
   // at each point of access.
   bool will_link(ciInstanceKlass* accessing_klass,
                  Bytecodes::Code bc);
+  bool will_link_from_vm(ciInstanceKlass* accessing_klass,
+                 Bytecodes::Code bc);
 
   // Java access flags
   bool is_public      () { return flags().is_public(); }
--- a/src/share/vm/ci/ciInstanceKlass.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/ci/ciInstanceKlass.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -64,17 +64,16 @@
   }
 
   Thread *thread = Thread::current();
-  if (ciObjectFactory::is_initialized()) {
+  if (ciObjectFactory::is_initialized() && !UseGraal) {
     _loader = JNIHandles::make_local(thread, ik->class_loader());
-    _protection_domain = JNIHandles::make_local(thread,
-                                                ik->protection_domain());
+    _protection_domain = JNIHandles::make_local(thread, ik->protection_domain());
     _is_shared = false;
   } else {
     Handle h_loader(thread, ik->class_loader());
     Handle h_protection_domain(thread, ik->protection_domain());
     _loader = JNIHandles::make_global(h_loader);
     _protection_domain = JNIHandles::make_global(h_protection_domain);
-    _is_shared = true;
+    _is_shared = !ciObjectFactory::is_initialized();
   }
 
   // Lazy fields get filled in only upon request.
--- a/src/share/vm/ci/ciInstanceKlass.hpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/ci/ciInstanceKlass.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -71,6 +71,19 @@
 
   GrowableArray<ciField*>* _non_static_fields;
 
+public:
+  virtual void cleanup() {
+    ciObject::cleanup();
+    if (!_is_shared) {
+      if (JNIHandles::is_global_handle(_loader)) {
+        JNIHandles::destroy_global(_loader);
+      }
+      if (JNIHandles::is_global_handle(_protection_domain)) {
+        JNIHandles::destroy_global(_protection_domain);
+      }
+    }
+  }
+
 protected:
   ciInstanceKlass(KlassHandle h_k);
   ciInstanceKlass(ciSymbol* name, jobject loader, jobject protection_domain);
--- a/src/share/vm/ci/ciObject.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/ci/ciObject.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -52,13 +52,19 @@
 ciObject::ciObject(oop o) {
   ASSERT_IN_VM;
   if (ciObjectFactory::is_initialized()) {
-    _handle = JNIHandles::make_local(o);
+    if (UseGraal) {
+      _handle = JNIHandles::make_global(o);
+      _temp_global = true;
+    } else {
+      _handle = JNIHandles::make_local(o);
+    }
   } else {
     _handle = JNIHandles::make_global(o);
   }
   _klass = NULL;
   _ident = 0;
   init_flags_from(o);
+  _temp_global = false;
 }
 
 // ------------------------------------------------------------------
@@ -67,13 +73,19 @@
 ciObject::ciObject(Handle h) {
   ASSERT_IN_VM;
   if (ciObjectFactory::is_initialized()) {
-    _handle = JNIHandles::make_local(h());
+    if (UseGraal) {
+      _handle = JNIHandles::make_global(h);
+      _temp_global = true;
+    } else {
+      _handle = JNIHandles::make_local(h());
+    }
   } else {
     _handle = JNIHandles::make_global(h);
   }
   _klass = NULL;
   _ident = 0;
   init_flags_from(h());
+  _temp_global = false;
 }
 
 // ------------------------------------------------------------------
@@ -87,6 +99,7 @@
   _handle = NULL;
   _klass = klass;
   _ident = 0;
+  _temp_global = false;
 }
 
 // ------------------------------------------------------------------
@@ -98,6 +111,7 @@
   _handle = NULL;
   _klass = NULL;
   _ident = 0;
+  _temp_global = false;
 }
 
 // ------------------------------------------------------------------
--- a/src/share/vm/ci/ciObject.hpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/ci/ciObject.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -58,6 +58,7 @@
   jobject  _handle;
   ciKlass* _klass;
   uint     _ident;
+  bool     _temp_global;
 
   enum { FLAG_BITS   = 2 };
   enum {
@@ -70,12 +71,19 @@
   ciObject(Handle h);
   ciObject(ciKlass* klass);
 
+public:
+  virtual void cleanup() {
+    if (_temp_global && _handle != NULL && JNIHandles::is_global_handle(_handle)) {
+      JNIHandles::destroy_global(_handle);
+    }
+  }
   jobject      handle()  const { return _handle; }
   // Get the VM oop that this object holds.
   oop get_oop() const {
     assert(_handle != NULL, "null oop");
     return JNIHandles::resolve_non_null(_handle);
   }
+protected:
 
   void init_flags_from(oop x) {
     int flags = 0;
--- a/src/share/vm/ci/ciObjectFactory.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/ci/ciObjectFactory.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -101,6 +101,14 @@
   _symbols = new (arena) GrowableArray<ciSymbol*>(arena, 100, 0, NULL);
 }
 
+void ciObjectFactory::cleanup() {
+  int start = 0;
+  if (_shared_ci_objects != NULL) start = _shared_ci_objects->length();
+  for (int i = start; i < _ci_objects->length(); ++i) {
+    _ci_objects->at(i)->cleanup();
+  }
+}
+
 // ------------------------------------------------------------------
 // ciObjectFactory::ciObjectFactory
 void ciObjectFactory::initialize() {
--- a/src/share/vm/ci/ciObjectFactory.hpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/ci/ciObjectFactory.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -94,6 +94,8 @@
 
   ciObjectFactory(Arena* arena, int expected_size);
 
+  void cleanup();
+
   // Get the ciObject corresponding to some oop.
   ciObject* get(oop key);
 
--- a/src/share/vm/ci/ciSymbol.hpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/ci/ciSymbol.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -53,8 +53,10 @@
   ciSymbol(Symbol* s);  // normal case, for symbols not mentioned in vmSymbols
   ciSymbol(Symbol* s, vmSymbols::SID sid);   // for use with vmSymbols
 
+public:
   Symbol* get_symbol() const { return _symbol; }
 
+private:
   const char* type_string() { return "ciSymbol"; }
 
   void print_impl(outputStream* st);
--- a/src/share/vm/classfile/systemDictionary.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/classfile/systemDictionary.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -190,7 +190,8 @@
 // Forwards to resolve_instance_class_or_null
 
 klassOop SystemDictionary::resolve_or_null(Symbol* class_name, Handle class_loader, Handle protection_domain, TRAPS) {
-  assert(!THREAD->is_Compiler_thread(), "Can not load classes with the Compiler thread");
+  // (tw) May we do this?
+  //assert(!THREAD->is_Compiler_thread(), "Can not load classes with the Compiler thread");
   if (FieldType::is_array(class_name)) {
     return resolve_array_class_or_null(class_name, class_loader, protection_domain, CHECK_NULL);
   } else if (FieldType::is_obj(class_name)) {
@@ -2345,8 +2346,9 @@
   if (spe == NULL || spe->property_oop() == NULL) {
     spe = NULL;
     // Must create lots of stuff here, but outside of the SystemDictionary lock.
-    if (THREAD->is_Compiler_thread())
-      return NULL;              // do not attempt from within compiler
+    // (tw) May we do this?
+	//if (THREAD->is_Compiler_thread())
+    //  return NULL;              // do not attempt from within compiler
     bool for_invokeGeneric = (name_id != vmSymbols::VM_SYMBOL_ENUM_NAME(invokeExact_name));
     bool found_on_bcp = false;
     Handle mt = find_method_handle_type(signature, accessing_klass,
--- a/src/share/vm/classfile/systemDictionary.hpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/classfile/systemDictionary.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -182,6 +182,43 @@
   template(Short_klass,                  java_lang_Short,                Pre) \
   template(Integer_klass,                java_lang_Integer,              Pre) \
   template(Long_klass,                   java_lang_Long,                 Pre) \
+                                                                              \
+  template(graalOptions_klass,           com_sun_graal_graalOptions,                                Opt) \
+  template(HotSpotTypeResolved_klass,    com_sun_hotspot_graal_HotSpotTypeResolved,                 Opt) \
+  template(HotSpotType_klass,            com_sun_hotspot_graal_HotSpotType,                         Opt) \
+  template(HotSpotField_klass,           com_sun_hotspot_graal_HotSpotField,                        Opt) \
+  template(HotSpotMethodResolved_klass,  com_sun_hotspot_graal_HotSpotMethodResolved,               Opt) \
+  template(HotSpotTargetMethod_klass,    com_sun_hotspot_graal_HotSpotTargetMethod,                 Opt) \
+  template(HotSpotExceptionHandler_klass,com_sun_hotspot_graal_HotSpotExceptionHandler,             Opt) \
+  template(HotSpotProxy_klass,           com_sun_hotspot_graal_HotSpotProxy,                        Opt) \
+  template(CiAssumptions_klass,          com_sun_cri_ci_CiAssumptions,                              Opt) \
+  template(CiAssumptions_ConcreteSubtype_klass, com_sun_cri_ci_CiAssumptions_ConcreteSubtype,       Opt) \
+  template(CiAssumptions_ConcreteMethod_klass,  com_sun_cri_ci_CiAssumptions_ConcreteMethod,        Opt) \
+  template(CiTargetMethod_klass,         com_sun_cri_ci_CiTargetMethod,                             Opt) \
+  template(CiTargetMethod_Site_klass,    com_sun_cri_ci_CiTargetMethod_Site,                        Opt) \
+  template(CiTargetMethod_Call_klass,    com_sun_cri_ci_CiTargetMethod_Call,                        Opt) \
+  template(CiTargetMethod_DataPatch_klass, com_sun_cri_ci_CiTargetMethod_DataPatch,                 Opt) \
+  template(CiTargetMethod_Safepoint_klass, com_sun_cri_ci_CiTargetMethod_Safepoint,                 Opt) \
+  template(CiTargetMethod_ExceptionHandler_klass, com_sun_cri_ci_CiTargetMethod_ExceptionHandler,   Opt) \
+  template(CiTargetMethod_Mark_klass,    com_sun_cri_ci_CiTargetMethod_Mark,                        Opt) \
+  template(GraalBitMap_klass,            com_oracle_max_graal_graph_BitMap,                         Opt) \
+  template(CiDebugInfo_klass,            com_sun_cri_ci_CiDebugInfo,                                Opt) \
+  template(CiFrame_klass,                com_sun_cri_ci_CiFrame,                                    Opt) \
+  template(CiValue_klass,                com_sun_cri_ci_CiValue,                                    Opt) \
+  template(CiStackSlot_klass,            com_sun_cri_ci_CiStackSlot,                                Opt) \
+  template(CiRegisterValue_klass,        com_sun_cri_ci_CiRegisterValue,                            Opt) \
+  template(CiRegister_klass,             com_sun_cri_ci_CiRegister,                                 Opt) \
+  template(CiCodePos_klass,              com_sun_cri_ci_CiCodePos,                                  Opt) \
+  template(CiConstant_klass,             com_sun_cri_ci_CiConstant,                                 Opt) \
+  template(CiVirtualObject_klass,        com_sun_cri_ci_CiVirtualObject,                            Opt) \
+  template(CiKind_klass,                 com_sun_cri_ci_CiKind,                                     Opt) \
+  template(CiRuntimeCall_klass,          com_sun_cri_ci_CiRuntimeCall,                              Opt) \
+  template(RiMethod_klass,               com_sun_cri_ri_RiMethod,                                   Opt) \
+  template(RiType_klass,                 com_sun_cri_ri_RiType,                                     Opt) \
+  template(RiField_klass,                com_sun_cri_ri_RiField,                                    Opt) \
+  template(RiExceptionHandler_klass,     com_sun_cri_ri_RiExceptionHandler,                         Opt) \
+  template(RiTypeProfile_klass,          com_sun_cri_ri_RiTypeProfile,                              Opt) \
+
   /*end*/
 
 
--- a/src/share/vm/classfile/vmSymbols.hpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/classfile/vmSymbols.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -257,7 +257,86 @@
   template(makeDynamicCallSite_signature, "(Ljava/lang/invoke/MethodHandle;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Object;Ljava/lang/invoke/MemberName;I)Ljava/lang/invoke/CallSite;") \
   NOT_LP64(  do_alias(machine_word_signature,         int_signature)  )                           \
   LP64_ONLY( do_alias(machine_word_signature,         long_signature) )                           \
-                                                                                                  \
+                                                                                                                        \
+  /* support for graal */                                                                                               \
+  template(com_sun_hotspot_graal_VMExits,             "com/oracle/max/graal/runtime/VMExits")                           \
+  template(com_sun_hotspot_graal_HotSpotMethodResolved, "com/oracle/max/graal/runtime/HotSpotMethodResolvedImpl")       \
+  template(com_sun_hotspot_graal_HotSpotTargetMethod, "com/oracle/max/graal/runtime/HotSpotTargetMethod")               \
+  template(com_sun_hotspot_graal_HotSpotField,        "com/oracle/max/graal/runtime/HotSpotField")                      \
+  template(com_sun_graal_graalOptions,                "com/sun/graal/graalOptions")                                     \
+  template(com_sun_hotspot_graal_HotSpotOptions,      "com/oracle/max/graal/runtime/HotSpotOptions")                    \
+  template(com_sun_hotspot_graal_HotSpotTypeResolved, "com/oracle/max/graal/runtime/HotSpotTypeResolvedImpl")           \
+  template(com_sun_hotspot_graal_HotSpotType,         "com/oracle/max/graal/runtime/HotSpotType")                       \
+  template(com_sun_hotspot_graal_HotSpotExceptionHandler,"com/oracle/max/graal/runtime/HotSpotExceptionHandler")        \
+  template(com_sun_hotspot_graal_HotSpotProxy,        "com/oracle/max/graal/runtime/HotSpotProxy")                      \
+  template(com_sun_hotspot_graal_Compiler,            "com/oracle/max/graal/runtime/Compiler")                          \
+  template(com_sun_hotspot_graal_CompilerImpl,        "com/oracle/max/graal/runtime/CompilerImpl")                      \
+  template(com_sun_cri_ri_RiMethod,                   "com/sun/cri/ri/RiMethod")                                        \
+  template(com_sun_cri_ri_RiField,                    "com/sun/cri/ri/RiField")                                         \
+  template(com_sun_cri_ri_RiType,                     "com/sun/cri/ri/RiType")                                          \
+  template(com_sun_cri_ri_RiTypeProfile,              "com/sun/cri/ri/RiTypeProfile")                                   \
+  template(com_sun_cri_ri_RiConstantPool,             "com/sun/cri/ri/RiConstantPool")                                  \
+  template(com_sun_cri_ri_RiExceptionHandler,         "com/sun/cri/ri/RiExceptionHandler")                              \
+  template(com_sun_cri_ci_CiAssumptions,              "com/sun/cri/ci/CiAssumptions")                                   \
+  template(com_sun_cri_ci_CiAssumptions_ConcreteSubtype, "com/sun/cri/ci/CiAssumptions$ConcreteSubtype")                \
+  template(com_sun_cri_ci_CiAssumptions_ConcreteMethod, "com/sun/cri/ci/CiAssumptions$ConcreteMethod")                  \
+  template(com_sun_cri_ci_CiTargetMethod,             "com/sun/cri/ci/CiTargetMethod")                                  \
+  template(com_sun_cri_ci_CiTargetMethod_Site,        "com/sun/cri/ci/CiTargetMethod$Site")                             \
+  template(com_sun_cri_ci_CiTargetMethod_Call,        "com/sun/cri/ci/CiTargetMethod$Call")                             \
+  template(com_sun_cri_ci_CiTargetMethod_DataPatch,   "com/sun/cri/ci/CiTargetMethod$DataPatch")                        \
+  template(com_sun_cri_ci_CiTargetMethod_Safepoint,   "com/sun/cri/ci/CiTargetMethod$Safepoint")                        \
+  template(com_sun_cri_ci_CiTargetMethod_ExceptionHandler, "com/sun/cri/ci/CiTargetMethod$ExceptionHandler")            \
+  template(com_sun_cri_ci_CiTargetMethod_Mark,        "com/sun/cri/ci/CiTargetMethod$Mark")                             \
+  template(com_oracle_max_graal_graph_BitMap,         "com/oracle/max/graal/graph/BitMap")                              \
+  template(com_sun_cri_ci_CiDebugInfo,                "com/sun/cri/ci/CiDebugInfo")                                     \
+  template(com_sun_cri_ci_CiFrame,                    "com/sun/cri/ci/CiFrame")                                         \
+  template(com_sun_cri_ci_CiValue,                    "com/sun/cri/ci/CiValue")                                         \
+  template(com_sun_cri_ci_CiStackSlot,                "com/sun/cri/ci/CiStackSlot")                                     \
+  template(com_sun_cri_ci_CiRegisterValue,            "com/sun/cri/ci/CiRegisterValue")                                 \
+  template(com_sun_cri_ci_CiRegister,                 "com/sun/cri/ci/CiRegister")                                      \
+  template(com_sun_cri_ci_CiCodePos,                  "com/sun/cri/ci/CiCodePos")                                       \
+  template(com_sun_cri_ci_CiConstant,                 "com/sun/cri/ci/CiConstant")                                      \
+  template(com_sun_cri_ci_CiVirtualObject,            "com/sun/cri/ci/CiVirtualObject")                                 \
+  template(com_sun_cri_ci_CiKind,                     "com/sun/cri/ci/CiKind")                                          \
+  template(com_sun_cri_ci_CiRuntimeCall,              "com/sun/cri/ci/CiRuntimeCall")                                   \
+  template(startCompiler_name,                        "startCompiler")                                                  \
+  template(shutdownCompiler_name,                     "shutdownCompiler")                                               \
+  template(compileMethod_name,                        "compileMethod")                                                  \
+  template(compileMethod_signature,                   "(Lcom/oracle/max/graal/runtime/HotSpotMethodResolved;I)V")       \
+  template(setOption_name,                            "setOption")                                                      \
+  template(setDefaultOptions_name,                    "setDefaultOptions")                                              \
+  template(setOption_signature,                       "(Ljava/lang/String;)Z")                                          \
+  template(createRiMethodResolved_name,               "createRiMethodResolved")                                         \
+  template(createRiMethodResolved_signature,          "(JLjava/lang/String;)Lcom/sun/cri/ri/RiMethod;")                 \
+  template(createRiMethodUnresolved_name,             "createRiMethodUnresolved")                                       \
+  template(createRiMethodUnresolved_signature,        "(Ljava/lang/String;Ljava/lang/String;Lcom/sun/cri/ri/RiType;)Lcom/sun/cri/ri/RiMethod;") \
+  template(createRiSignature_name,                    "createRiSignature")                                              \
+  template(createRiSignature_signature,               "(Ljava/lang/String;)Lcom/sun/cri/ri/RiSignature;")               \
+  template(createRiField_name,                        "createRiField")                                                  \
+  template(createRiField_signature,                   "(Lcom/sun/cri/ri/RiType;Ljava/lang/String;Lcom/sun/cri/ri/RiType;II)Lcom/sun/cri/ri/RiField;") \
+  template(createRiType_name,                         "createRiType")                                                   \
+  template(createRiType_signature,                    "(JLjava/lang/String;)Lcom/sun/cri/ri/RiType;")                   \
+  template(createRiTypePrimitive_name,                "createRiTypePrimitive")                                          \
+  template(createRiTypePrimitive_signature,           "(I)Lcom/sun/cri/ri/RiType;")                                     \
+  template(createRiTypeUnresolved_name,               "createRiTypeUnresolved")                                         \
+  template(createRiTypeUnresolved_signature,          "(Ljava/lang/String;)Lcom/sun/cri/ri/RiType;")                    \
+  template(createRiConstantPool_name,                 "createRiConstantPool")                                           \
+  template(createRiConstantPool_signature,            "(J)Lcom/sun/cri/ri/RiConstantPool;")                             \
+  template(createCiConstant_name,                     "createCiConstant")                                               \
+  template(createCiConstant_signature,                "(Lcom/sun/cri/ci/CiKind;J)Lcom/sun/cri/ci/CiConstant;")          \
+  template(createCiConstantFloat_name,                "createCiConstantFloat")                                          \
+  template(createCiConstantFloat_signature,           "(F)Lcom/sun/cri/ci/CiConstant;")                                 \
+  template(createCiConstantDouble_name,               "createCiConstantDouble")                                         \
+  template(createCiConstantDouble_signature,          "(D)Lcom/sun/cri/ci/CiConstant;")                                 \
+  template(createCiConstantObject_name,               "createCiConstantObject")                                         \
+  template(createCiConstantObject_signature,          "(Ljava/lang/Object;)Lcom/sun/cri/ci/CiConstant;")                \
+  template(getVMExits_name,                           "getVMExits")                                                     \
+  template(getVMExits_signature,                      "()Lcom/oracle/max/graal/runtime/VMExits;")                       \
+  template(getInstance_name,                          "getInstance")                                                    \
+  template(initialize_name,                           "initialize")                                                     \
+  template(getInstance_signature,                     "()Lcom/oracle/max/graal/runtime/Compiler;")                      \
+  template(forObject_name,                            "forObject")                                                      \
+                                                                                                                        \
   /* common method and field names */                                                             \
   template(object_initializer_name,                   "<init>")                                   \
   template(class_initializer_name,                    "<clinit>")                                 \
--- a/src/share/vm/code/codeBlob.hpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/code/codeBlob.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -405,6 +405,11 @@
 
   int _unpack_with_exception_in_tls;
 
+  // (tw) Offset when graal calls uncommon_trap.
+  int _uncommon_trap_offset;
+  int _jmp_uncommon_trap_offset;
+
+
   // Creation support
   DeoptimizationBlob(
     CodeBuffer* cb,
@@ -457,6 +462,19 @@
     assert(code_contains(code_begin() + _unpack_with_exception_in_tls), "must be PC inside codeblob");
   }
   address unpack_with_exception_in_tls() const   { return code_begin() + _unpack_with_exception_in_tls; }
+
+  // (tw) 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_jmp_uncommon_trap_offset(int offset) {
+    _jmp_uncommon_trap_offset = offset;
+    assert(contains(code_begin() + _jmp_uncommon_trap_offset), "must be PC inside codeblob");
+  }
+  address jmp_uncommon_trap() const                  { return code_begin() + _jmp_uncommon_trap_offset;     }
+
 };
 
 
--- a/src/share/vm/code/compiledIC.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/code/compiledIC.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -529,7 +529,7 @@
   NativeJump*        jump          = nativeJump_at(method_holder->next_instruction_address());
 
   assert(method_holder->data()    == 0           || method_holder->data()    == (intptr_t)callee(), "a) MT-unsafe modification of inline cache");
-  assert(jump->jump_destination() == (address)-1 || jump->jump_destination() == entry, "b) MT-unsafe modification of inline cache");
+  assert(UseGraal || jump->jump_destination() == (address)-1 || jump->jump_destination() == entry, "b) MT-unsafe modification of inline cache");
 
   // Update stub
   method_holder->set_data((intptr_t)callee());
--- a/src/share/vm/code/debugInfoRec.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/code/debugInfoRec.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -283,6 +283,7 @@
                                               ciMethod*   method,
                                               int         bci,
                                               bool        reexecute,
+                                              bool        rethrow_exception,
                                               bool        is_method_handle_invoke,
                                               bool        return_oop,
                                               DebugToken* locals,
@@ -298,6 +299,7 @@
 
   // Record flags into pcDesc.
   last_pd->set_should_reexecute(reexecute);
+  last_pd->set_rethrow_exception(rethrow_exception);
   last_pd->set_is_method_handle_invoke(is_method_handle_invoke);
   last_pd->set_return_oop(return_oop);
 
--- a/src/share/vm/code/debugInfoRec.hpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/code/debugInfoRec.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -101,6 +101,7 @@
                       ciMethod*   method,
                       int         bci,
                       bool        reexecute,
+                      bool        rethrow_exception,
                       bool        is_method_handle_invoke = false,
                       bool        return_oop = false,
                       DebugToken* locals      = NULL,
--- a/src/share/vm/code/nmethod.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/code/nmethod.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -818,12 +818,23 @@
     // Exception handler and deopt handler are in the stub section
     assert(offsets->value(CodeOffsets::Exceptions) != -1, "must be set");
     assert(offsets->value(CodeOffsets::Deopt     ) != -1, "must be set");
-    _exception_offset        = _stub_offset          + offsets->value(CodeOffsets::Exceptions);
-    _deoptimize_offset       = _stub_offset          + offsets->value(CodeOffsets::Deopt);
-    if (offsets->value(CodeOffsets::DeoptMH) != -1) {
-      _deoptimize_mh_offset  = _stub_offset          + offsets->value(CodeOffsets::DeoptMH);
+    if (UseGraal) {
+      // graal produces no (!) stub section
+      _exception_offset        = code_offset()          + offsets->value(CodeOffsets::Exceptions);
+      _deoptimize_offset       = code_offset()          + offsets->value(CodeOffsets::Deopt);
+      if (offsets->value(CodeOffsets::DeoptMH) != -1) {
+        _deoptimize_mh_offset  = code_offset()          + offsets->value(CodeOffsets::DeoptMH);
+      } else {
+        _deoptimize_mh_offset  = -1;
+      }
     } else {
-      _deoptimize_mh_offset  = -1;
+      _exception_offset        = _stub_offset          + offsets->value(CodeOffsets::Exceptions);
+      _deoptimize_offset       = _stub_offset          + offsets->value(CodeOffsets::Deopt);
+      if (offsets->value(CodeOffsets::DeoptMH) != -1) {
+        _deoptimize_mh_offset  = _stub_offset          + offsets->value(CodeOffsets::DeoptMH);
+      } else {
+        _deoptimize_mh_offset  = -1;
+      }
     }
     if (offsets->value(CodeOffsets::UnwindHandler) != -1) {
       _unwind_handler_offset = code_offset()         + offsets->value(CodeOffsets::UnwindHandler);
@@ -1068,7 +1079,7 @@
   PcDesc* pd = pc_desc_at(pc);
   guarantee(pd != NULL, "scope must be present");
   return new ScopeDesc(this, pd->scope_decode_offset(),
-                       pd->obj_decode_offset(), pd->should_reexecute(),
+                       pd->obj_decode_offset(), pd->should_reexecute(), pd->rethrow_exception(),
                        pd->return_oop());
 }
 
@@ -2258,7 +2269,7 @@
   PcDesc* pd = pc_desc_at(ic->end_of_call());
   assert(pd != NULL, "PcDesc must exist");
   for (ScopeDesc* sd = new ScopeDesc(this, pd->scope_decode_offset(),
-                                     pd->obj_decode_offset(), pd->should_reexecute(),
+                                     pd->obj_decode_offset(), pd->should_reexecute(), pd->rethrow_exception(),
                                      pd->return_oop());
        !sd->is_top(); sd = sd->sender()) {
     sd->verify();
@@ -2292,7 +2303,7 @@
         // information in a table.
         break;
     }
-    assert(stub == NULL || stub_contains(stub), "static call stub outside stub section");
+    assert(UseGraal || stub == NULL || stub_contains(stub), "static call stub outside stub section");
   }
 }
 
@@ -2524,7 +2535,7 @@
   PcDesc* p = pc_desc_near(begin+1);
   if (p != NULL && p->real_pc(this) <= end) {
     return new ScopeDesc(this, p->scope_decode_offset(),
-                         p->obj_decode_offset(), p->should_reexecute(),
+                         p->obj_decode_offset(), p->should_reexecute(), p->rethrow_exception(),
                          p->return_oop());
   }
   return NULL;
--- a/src/share/vm/code/nmethod.hpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/code/nmethod.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -590,7 +590,10 @@
   // Deopt
   // Return true is the PC is one would expect if the frame is being deopted.
   bool is_deopt_pc      (address pc) { return is_deopt_entry(pc) || is_deopt_mh_entry(pc); }
-  bool is_deopt_entry   (address pc) { return pc == deopt_handler_begin(); }
+
+  // (tw) When using graal, the address might be off by 5 (because this is the size of the call instruction.
+  // (tw) TODO: Replace this by a more general mechanism.
+  bool is_deopt_entry   (address pc) { return pc == deopt_handler_begin() || (UseGraal && pc == deopt_handler_begin() + 5); }
   bool is_deopt_mh_entry(address pc) { return pc == deopt_mh_handler_begin(); }
   // Accessor/mutator for the original pc of a frame before a frame was deopted.
   address get_original_pc(const frame* fr) { return *orig_pc_addr(fr); }
--- a/src/share/vm/code/pcDesc.hpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/code/pcDesc.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -43,6 +43,7 @@
     int word;
     struct {
       unsigned int reexecute: 1;
+      unsigned int rethrow_exception: 1;
       unsigned int is_method_handle_invoke: 1;
       unsigned int return_oop: 1;
     } bits;
@@ -71,6 +72,8 @@
   // Flags
   bool     should_reexecute()              const { return _flags.bits.reexecute; }
   void set_should_reexecute(bool z)              { _flags.bits.reexecute = z;    }
+  bool     rethrow_exception()              const { return _flags.bits.rethrow_exception; }
+  void set_rethrow_exception(bool z)              { _flags.bits.rethrow_exception = z;    }
 
   // Does pd refer to the same information as pd?
   bool is_same_info(const PcDesc* pd) {
--- a/src/share/vm/code/scopeDesc.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/code/scopeDesc.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -31,21 +31,23 @@
 #include "runtime/handles.inline.hpp"
 
 
-ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute, bool return_oop) {
+ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute, bool rethrow_exception, bool return_oop) {
   _code          = code;
   _decode_offset = decode_offset;
   _objects       = decode_object_values(obj_decode_offset);
   _reexecute     = reexecute;
   _return_oop    = return_oop;
+  _rethrow_exception = rethrow_exception;
   decode_body();
 }
 
-ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, bool reexecute, bool return_oop) {
+ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, bool reexecute, bool rethrow_exception, bool return_oop) {
   _code          = code;
   _decode_offset = decode_offset;
   _objects       = decode_object_values(DebugInformationRecorder::serialized_null);
   _reexecute     = reexecute;
   _return_oop    = return_oop;
+  _rethrow_exception = rethrow_exception;
   decode_body();
 }
 
@@ -55,6 +57,7 @@
   _decode_offset = parent->_sender_decode_offset;
   _objects       = parent->_objects;
   _reexecute     = false; //reexecute only applies to the first scope
+  _rethrow_exception = false;
   _return_oop    = false;
   decode_body();
 }
--- a/src/share/vm/code/scopeDesc.hpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/code/scopeDesc.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -60,17 +60,18 @@
 class ScopeDesc : public ResourceObj {
  public:
   // Constructor
-  ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute, bool return_oop);
+  ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute, bool rethrow_exception, bool return_oop);
 
   // Calls above, giving default value of "serialized_null" to the
   // "obj_decode_offset" argument.  (We don't use a default argument to
   // avoid a .hpp-.hpp dependency.)
-  ScopeDesc(const nmethod* code, int decode_offset, bool reexecute, bool return_oop);
+  ScopeDesc(const nmethod* code, int decode_offset, bool reexecute, bool rethrow_exception, bool return_oop);
 
   // JVM state
   methodHandle method()   const { return _method; }
   int          bci()      const { return _bci;    }
   bool should_reexecute() const { return _reexecute; }
+  bool rethrow_exception() const { return _rethrow_exception; }
   bool return_oop()       const { return _return_oop; }
 
   GrowableArray<ScopeValue*>*   locals();
@@ -97,6 +98,7 @@
   methodHandle  _method;
   int           _bci;
   bool          _reexecute;
+  bool          _rethrow_exception;
   bool          _return_oop;
 
   // Decoding offsets
--- a/src/share/vm/compiler/abstractCompiler.hpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/compiler/abstractCompiler.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -72,9 +72,6 @@
 #endif // SHARK
 #endif // TIERED
 
-  // Customization
-  virtual bool needs_stubs            ()         = 0;
-
   void mark_initialized()                        { _is_initialized = true; }
   bool is_initialized()                          { return _is_initialized; }
 
--- a/src/share/vm/compiler/compileBroker.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/compiler/compileBroker.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -44,6 +44,7 @@
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/sweeper.hpp"
 #include "utilities/dtrace.hpp"
+#include "graal/graalCompiler.hpp"
 #ifdef COMPILER1
 #include "c1/c1_Compiler.hpp"
 #endif
@@ -585,6 +586,9 @@
     assert(task == _last, "Sanity");
     _last = task->prev();
   }
+
+  // (tw) Immediately set compiling flag.
+  JavaThread::current()->as_CompilerThread()->set_compiling(true);
   --_size;
 }
 
@@ -638,6 +642,74 @@
   }
 }
 
+// Bootstrap the graal compiler. Compiles all methods until compile queue is empty and no compilation is active.
+void CompileBroker::bootstrap_graal() {
+  HandleMark hm;
+  Thread* THREAD = Thread::current();
+  tty->print_cr("Bootstrapping graal....");
+
+  GraalCompiler* compiler = GraalCompiler::instance();
+  if (compiler == NULL) fatal("must use flag -XX:+UseGraal");
+
+  jlong start = os::javaTimeMillis();
+
+  instanceKlass* klass = (instanceKlass*)SystemDictionary::Object_klass()->klass_part();
+  methodOop method = klass->find_method(vmSymbols::object_initializer_name(), vmSymbols::void_method_signature());
+  CompileBroker::compile_method(method, -1, 0, method, 0, "initial compile of object initializer", THREAD);
+  if (HAS_PENDING_EXCEPTION) {
+    CLEAR_PENDING_EXCEPTION;
+    fatal("error inserting object initializer into compile queue");
+  }
+
+  int z = 0;
+  while (true) {
+    {
+      HandleMark hm;
+      ResourceMark rm;
+      MutexLocker locker(_c1_method_queue->lock(), Thread::current());
+      if (_c1_method_queue->is_empty()) {
+        MutexLocker mu(Threads_lock); // grab Threads_lock
+        JavaThread* current = Threads::first();
+        bool compiling = false;
+        while (current != NULL) {
+          if (current->is_Compiler_thread()) {
+            CompilerThread* comp_thread = current->as_CompilerThread();
+            if (comp_thread->is_compiling()) {
+              if (TraceGraal >= 4) {
+                tty->print_cr("Compile queue empty, but following thread is still compiling:");
+                comp_thread->print();
+              }
+              compiling = true;
+            }
+          }
+          current = current->next();
+        }
+        if (!compiling) {
+          break;
+        }
+      }
+      if (TraceGraal >= 5) {
+        _c1_method_queue->print();
+      }
+    }
+
+    {
+      //ThreadToNativeFromVM trans(JavaThread::current());
+      os::sleep(THREAD, 10, true);
+    }
+    ++z;
+  }
+
+  // Do a full garbage collection.
+  Universe::heap()->collect(GCCause::_java_lang_system_gc);
+
+  jlong diff = os::javaTimeMillis() - start;
+  tty->print_cr("Finished bootstrap in %d ms", diff);
+  if (CITime) CompileBroker::print_times();
+  tty->print_cr("===========================================================================");
+}
+
+
 // ------------------------------------------------------------------
 // CompileBroker::compilation_init
 //
@@ -650,9 +722,14 @@
   int c1_count = CompilationPolicy::policy()->compiler_count(CompLevel_simple);
   int c2_count = CompilationPolicy::policy()->compiler_count(CompLevel_full_optimization);
 #ifdef COMPILER1
-  if (c1_count > 0) {
-    _compilers[0] = new Compiler();
+  if (UseGraal) {
+	  _compilers[0] = new GraalCompiler();
+  } else if (c1_count > 0) {
+	  _compilers[0] = new Compiler();
   }
+#ifndef COMPILER2
+  _compilers[1] = _compilers[0];
+#endif
 #endif // COMPILER1
 
 #ifdef COMPILER2
@@ -1009,6 +1086,13 @@
   {
     MutexLocker locker(queue->lock(), THREAD);
 
+    if (Thread::current()->is_Compiler_thread() && CompilerThread::current()->is_compiling() && !BackgroundCompilation) {
+
+      TRACE_graal_1("Recursive compile %s!", method->name_and_sig_as_C_string());
+      method->set_not_compilable();
+      return;
+    }
+
     // Make sure the method has not slipped into the queues since
     // last we checked; note that those checks were "fast bail-outs".
     // Here we need to be more careful, see 14012000 below.
@@ -1465,9 +1549,18 @@
     log->stamp();
     log->end_elem();
   }
+  
+  if (UseGraal) {
+    thread->set_compiling(true); // Prevent recursive compilations while the compiler is initializing.
+    ThreadToNativeFromVM trans(JavaThread::current());
+    GraalCompiler::instance()->initialize();
+  }
 
   while (true) {
     {
+      // Unset compiling flag.
+      thread->set_compiling(false);
+
       // We need this HandleMark to avoid leaking VM handles.
       HandleMark hm(thread);
 
@@ -1611,6 +1704,7 @@
 void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
   if (PrintCompilation) {
     ResourceMark rm;
+    tty->print("%s: ", compiler(task->comp_level())->name());
     task->print_line();
   }
   elapsedTimer time;
@@ -1646,15 +1740,17 @@
   // Allocate a new set of JNI handles.
   push_jni_handle_block();
   jobject target_handle = JNIHandles::make_local(thread, JNIHandles::resolve(task->method_handle()));
-  int compilable = ciEnv::MethodCompilable;
-  {
+  int compilable = ciEnv::MethodCompilable_never;
+  if (MaxCompilationID == -1 || compile_id <= (uint)MaxCompilationID) {
+    compilable = ciEnv::MethodCompilable;
     int system_dictionary_modification_counter;
     {
       MutexLocker locker(Compile_lock, thread);
       system_dictionary_modification_counter = SystemDictionary::number_of_modifications();
     }
 
-    NoHandleMark  nhm;
+	// (tw) Check if we may do this?
+    // NoHandleMark  nhm;
     ThreadToNativeFromVM ttn(thread);
 
     ciEnv ci_env(task, system_dictionary_modification_counter);
--- a/src/share/vm/compiler/compileBroker.hpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/compiler/compileBroker.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -401,6 +401,8 @@
   static void print_last_compile();
 
   static void print_compiler_threads_on(outputStream* st);
+
+  static void bootstrap_graal();
 };
 
 #endif // SHARE_VM_COMPILER_COMPILEBROKER_HPP
--- a/src/share/vm/compiler/compilerOracle.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/compiler/compilerOracle.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -471,7 +471,7 @@
   line += bytes_read;
 
   if (command == UnknownCommand) {
-    tty->print_cr("CompilerOracle: unrecognized line");
+    tty->print_cr("CompilerOracle: UnknownCommand");
     tty->print_cr("  \"%s\"", original_line);
     return;
   }
--- a/src/share/vm/compiler/oopMap.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/compiler/oopMap.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -255,7 +255,7 @@
   if(om_count() > 0) {
     OopMap* last = at(om_count()-1);
     if (last->offset() == map->offset() ) {
-      fatal("OopMap inserted twice");
+      fatal(err_msg("OopMap inserted twice (offset=%d)", last->offset()));
     }
     if(last->offset() > map->offset()) {
       tty->print_cr( "WARNING, maps not sorted: pc[%d]=%d, pc[%d]=%d",
--- a/src/share/vm/compiler/oopMap.hpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/compiler/oopMap.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -47,7 +47,7 @@
 class OopMapValue: public StackObj {
   friend class VMStructs;
 private:
-  short _value;
+  int _value;
   int value() const                                 { return _value; }
   void set_value(int value)                         { _value = value; }
   short _content_reg;
@@ -55,7 +55,7 @@
 public:
   // Constants
   enum { type_bits                = 5,
-         register_bits            = BitsPerShort - type_bits };
+         register_bits            = BitsPerJavaInteger - type_bits };
 
   enum { type_shift               = 0,
          register_shift           = type_bits };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,835 @@
+/*
+ * 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.
+ */
+
+#include "precompiled.hpp"
+#include "graal/graalCompiler.hpp"
+#include "graal/graalCodeInstaller.hpp"
+#include "graal/graalJavaAccess.hpp"
+#include "graal/graalVMEntries.hpp"
+#include "graal/graalVmIds.hpp"
+#include "c1/c1_Runtime1.hpp"
+#include "classfile/vmSymbols.hpp"
+#include "vmreg_x86.inline.hpp"
+
+
+// TODO this should be handled in a more robust way - not hard coded...
+Register CPU_REGS[] = { rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15 };
+bool OOP_ALLOWED[] = {true, true, true, true, false, false, true, true, true, true, false, true, true, true, true, true};
+const static int NUM_CPU_REGS = sizeof(CPU_REGS) / sizeof(Register);
+XMMRegister XMM_REGS[] = { xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 };
+const static int NUM_XMM_REGS = sizeof(XMM_REGS) / sizeof(XMMRegister);
+const static int NUM_REGS = NUM_CPU_REGS + NUM_XMM_REGS;
+const static jlong NO_REF_MAP = 0x8000000000000000L;
+
+// convert graal register indices (as used in oop maps) to hotspot registers
+VMReg get_hotspot_reg(jint graal_reg) {
+
+  assert(graal_reg >= 0 && graal_reg < NUM_REGS, "invalid register number");
+  if (graal_reg < NUM_CPU_REGS) {
+    return CPU_REGS[graal_reg]->as_VMReg();
+  } else {
+    return XMM_REGS[graal_reg - NUM_CPU_REGS]->as_VMReg();
+  }
+}
+
+static bool is_bit_set(oop bit_map, int i) {
+  const int MapWordBits = 64;
+  if (i < MapWordBits) {
+    jlong low = GraalBitMap::low(bit_map);
+    return (low & (1LL << i)) != 0;
+  } else {
+    jint extra_idx = (i - MapWordBits) / MapWordBits;
+    arrayOop extra = (arrayOop) GraalBitMap::extra(bit_map);
+    assert(extra_idx >= 0 && extra_idx < extra->length(), "unexpected index");
+    jlong word = ((jlong*) extra->base(T_LONG))[extra_idx];
+    return (word & (1LL << (i % MapWordBits))) != 0;
+  }
+}
+
+// creates a hotspot oop map out of the byte arrays provided by CiDebugInfo
+static OopMap* create_oop_map(jint frame_size, jint parameter_count, oop debug_info) {
+  OopMap* map = new OopMap(frame_size, parameter_count);
+  oop register_map = (oop) CiDebugInfo::registerRefMap(debug_info);
+  oop frame_map = (oop) CiDebugInfo::frameRefMap(debug_info);
+
+  if (register_map != NULL) {
+    assert(GraalBitMap::size(register_map) == (unsigned) NUM_CPU_REGS, "unexpected register_map length");
+    for (jint i = 0; i < NUM_CPU_REGS; i++) {
+      bool is_oop = is_bit_set(register_map, i);
+      VMReg reg = get_hotspot_reg(i);
+      if (is_oop) {
+        assert(OOP_ALLOWED[i], "this register may never be an oop, register map misaligned?");
+        map->set_oop(reg);
+      } else {
+        map->set_value(reg);
+      }
+    }
+  }
+
+  if (frame_size > 0) {
+    assert(GraalBitMap::size(frame_map) == frame_size / HeapWordSize, "unexpected frame_map length");
+
+    for (jint i = 0; i < frame_size / HeapWordSize; i++) {
+      bool is_oop = is_bit_set(frame_map, i);
+      // hotspot stack slots are 4 bytes
+      VMReg reg = VMRegImpl::stack2reg(i * 2);
+      if (is_oop) {
+        map->set_oop(reg);
+      } else {
+        map->set_value(reg);
+      }
+    }
+  } else {
+    assert(frame_map == NULL || GraalBitMap::size(frame_map) == 0, "cannot have frame_map for frames with size 0");
+  }
+
+  return map;
+}
+
+// TODO: finish this - graal doesn't provide any scope values at the moment
+static ScopeValue* get_hotspot_value(oop value, int frame_size, GrowableArray<ScopeValue*>* objects, ScopeValue* &second) {
+  second = NULL;
+  if (value == CiValue::IllegalValue()) {
+    return new LocationValue(Location::new_stk_loc(Location::invalid, 0));
+  }
+
+  BasicType type = GraalCompiler::kindToBasicType(CiKind::typeChar(CiValue::kind(value)));
+  Location::Type locationType = Location::normal;
+  if (type == T_OBJECT || type == T_ARRAY) locationType = Location::oop;
+
+  if (value->is_a(CiRegisterValue::klass())) {
+    jint number = CiRegister::number(CiRegisterValue::reg(value));
+    if (number < 16) {
+      if (type == T_INT || type == T_FLOAT || type == T_SHORT || type == T_CHAR || type == T_BOOLEAN || type == T_BYTE) {
+        locationType = Location::int_in_long;
+      } else if (type == T_LONG) {
+        locationType = Location::lng;
+      } else {
+        assert(type == T_OBJECT || type == T_ARRAY, "unexpected type in cpu register");
+      }
+      ScopeValue* value = new LocationValue(Location::new_reg_loc(locationType, as_Register(number)->as_VMReg()));
+      if (type == T_LONG) {
+        second = value;
+      }
+      return value;
+    } else {
+      assert(type == T_FLOAT || type == T_DOUBLE, "only float and double expected in xmm register");
+      if (type == T_FLOAT) {
+        // this seems weird, but the same value is used in c1_LinearScan
+        locationType = Location::normal;
+      } else {
+        locationType = Location::dbl;
+      }
+      ScopeValue* value = new LocationValue(Location::new_reg_loc(locationType, as_XMMRegister(number - 16)->as_VMReg()));
+      if (type == T_DOUBLE) {
+        second = value;
+      }
+      return value;
+    }
+  } else if (value->is_a(CiStackSlot::klass())) {
+    if (type == T_DOUBLE) {
+      locationType = Location::dbl;
+    } else if (type == T_LONG) {
+      locationType = Location::lng;
+    }
+    jint index = CiStackSlot::index(value);
+    ScopeValue* value;
+    if (index >= 0) {
+      value = new LocationValue(Location::new_stk_loc(locationType, index * HeapWordSize));
+    } else {
+      value = new LocationValue(Location::new_stk_loc(locationType, -(index * HeapWordSize) + frame_size));
+    }
+    if (type == T_DOUBLE || type == T_LONG) {
+      second = value;
+    }
+    return value;
+  } else if (value->is_a(CiConstant::klass())){
+    oop obj = CiConstant::object(value);
+    jlong prim = CiConstant::primitive(value);
+    if (type == T_INT || type == T_FLOAT || type == T_SHORT || type == T_CHAR || type == T_BOOLEAN || type == T_BYTE) {
+      return new ConstantIntValue(*(jint*)&prim);
+    } else if (type == T_LONG || type == T_DOUBLE) {
+      second = new ConstantIntValue(0);
+      return new ConstantLongValue(prim);
+    } else if (type == T_OBJECT) {
+      oop obj = CiConstant::object(value);
+      if (obj == NULL) {
+        return new ConstantOopWriteValue(NULL);
+      } else {
+        return new ConstantOopWriteValue(JNIHandles::make_global(obj));
+      }
+    } else if (type == T_ADDRESS) {
+      return new ConstantLongValue(prim);
+    }
+    tty->print("%i", type);
+  } else if (value->is_a(CiVirtualObject::klass())) {
+    oop type = CiVirtualObject::type(value);
+    int id = CiVirtualObject::id(value);
+    ciKlass* klass = (ciKlass*) CURRENT_ENV->get_object(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(type)));
+    assert(klass->is_instance_klass() || klass->is_array_klass(), "Not supported allocation.");
+
+    for (jint i = 0; i < objects->length(); i++) {
+      ObjectValue* obj = (ObjectValue*) objects->at(i);
+      if (obj->id() == id) {
+        return obj;
+      }
+    }
+
+    ObjectValue* sv = new ObjectValue(id, new ConstantOopWriteValue(klass->constant_encoding()));
+
+    arrayOop values = (arrayOop) CiVirtualObject::values(value);
+    for (jint i = 0; i < values->length(); i++) {
+      ((oop*) values->base(T_OBJECT))[i];
+    }
+
+    for (jint i = 0; i < values->length(); i++) {
+      ScopeValue* cur_second = NULL;
+      ScopeValue* value = get_hotspot_value(((oop*) values->base(T_OBJECT))[i], frame_size, objects, cur_second);
+      
+      if (cur_second != NULL) {
+        sv->field_values()->append(cur_second);
+      }
+      sv->field_values()->append(value);
+    }
+
+//    uint first_ind = spobj->first_index();
+//    for (uint i = 0; i < spobj->n_fields(); i++) {
+//      Node* fld_node = sfn->in(first_ind+i);
+//      (void)FillLocArray(sv->field_values()->length(), sfn, fld_node, sv->field_values(), objs);
+//    }
+//    scval = sv;
+
+    objects->append(sv);
+    return sv;
+  } else {
+    value->klass()->print();
+    value->print();
+  }
+  ShouldNotReachHere();
+  return NULL;
+}
+
+// constructor used to create a method
+CodeInstaller::CodeInstaller(Handle target_method) {
+  ciMethod *ciMethodObject = NULL;
+  {
+    No_Safepoint_Verifier no_safepoint;
+    _env = CURRENT_ENV;
+
+    initialize_fields(target_method);
+    assert(_hotspot_method != NULL && _name == NULL, "installMethod needs NON-NULL method and NULL name");
+    assert(_hotspot_method->is_a(HotSpotMethodResolved::klass()), "installMethod needs a HotSpotMethodResolved");
+
+    methodOop method = getMethodFromHotSpotMethod(_hotspot_method);
+    ciMethodObject = (ciMethod *) _env->get_object(method);
+    _parameter_count = method->size_of_parameters();
+  }
+
+  // (very) conservative estimate: each site needs a relocation
+  //CodeBuffer buffer("temp graal method", _total_size, _sites->length() * relocInfo::length_limit);
+  CodeBuffer buffer(CompilerThread::current()->get_buffer_blob());
+  initialize_buffer(buffer);
+  process_exception_handlers();
+
+  int stack_slots = (_frame_size / HeapWordSize) + 2; // conversion to words, need to add two slots for ret address and frame pointer
+  ThreadToNativeFromVM t((JavaThread*) Thread::current());
+  _env->register_method(ciMethodObject, -1, &_offsets, _custom_stack_area_offset, &buffer, stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table,
+      &_implicit_exception_table, GraalCompiler::instance(), _env->comp_level(), false, false);
+
+}
+
+// constructor used to create a stub
+CodeInstaller::CodeInstaller(Handle target_method, jlong& id) {
+  No_Safepoint_Verifier no_safepoint;
+  _env = CURRENT_ENV;
+
+  initialize_fields(target_method);
+  assert(_hotspot_method == NULL && _name != NULL, "installMethod needs NON-NULL name and NULL method");
+
+  // (very) conservative estimate: each site needs a relocation
+  CodeBuffer buffer(CompilerThread::current()->get_buffer_blob());
+  initialize_buffer(buffer);
+
+  const char* cname = java_lang_String::as_utf8_string(_name);
+  BufferBlob* blob = BufferBlob::create(strdup(cname), &buffer); // this is leaking strings... but only a limited number of stubs will be created
+  IF_TRACE_graal_3 Disassembler::decode((CodeBlob*) blob);
+  id = VmIds::addStub(blob->code_begin());
+}
+
+void CodeInstaller::initialize_fields(Handle target_method) {
+  _citarget_method = HotSpotTargetMethod::targetMethod(target_method);
+  _hotspot_method = HotSpotTargetMethod::method(target_method);
+  _name = HotSpotTargetMethod::name(target_method);
+  _sites = (arrayOop) HotSpotTargetMethod::sites(target_method);
+  oop assumptions = CiTargetMethod::assumptions(_citarget_method);
+  if (assumptions != NULL) {
+    _assumptions = (arrayOop) CiAssumptions::list(assumptions);
+  } else {
+    _assumptions = NULL;
+  }
+  _exception_handlers = (arrayOop) HotSpotTargetMethod::exceptionHandlers(target_method);
+
+  _code = (arrayOop) CiTargetMethod::targetCode(_citarget_method);
+  _code_size = CiTargetMethod::targetCodeSize(_citarget_method);
+  _frame_size = CiTargetMethod::frameSize(_citarget_method);
+  _custom_stack_area_offset = CiTargetMethod::customStackAreaOffset(_citarget_method);
+
+
+  // (very) conservative estimate: each site needs a constant section entry
+  _constants_size = _sites->length() * (BytesPerLong*2);
+  _total_size = align_size_up(_code_size, HeapWordSize) + _constants_size;
+
+  _next_call_type = MARK_INVOKE_INVALID;
+}
+
+// perform data and call relocation on the CodeBuffer
+void CodeInstaller::initialize_buffer(CodeBuffer& buffer) {
+  int locs_buffer_size = _sites->length() * (relocInfo::length_limit + sizeof(relocInfo));
+  char* locs_buffer = NEW_RESOURCE_ARRAY(char, locs_buffer_size);
+  buffer.insts()->initialize_shared_locs((relocInfo*)locs_buffer, locs_buffer_size / sizeof(relocInfo));
+  buffer.initialize_stubs_size(256);
+  buffer.initialize_consts_size(_constants_size);
+
+  _oop_recorder = new OopRecorder(_env->arena());
+  _env->set_oop_recorder(_oop_recorder);
+  _debug_recorder = new DebugInformationRecorder(_env->oop_recorder());
+  _debug_recorder->set_oopmaps(new OopMapSet());
+  _dependencies = new Dependencies(_env);
+
+  _env->set_oop_recorder(_oop_recorder);
+  _env->set_debug_info(_debug_recorder);
+  _env->set_dependencies(_dependencies);
+  buffer.initialize_oop_recorder(_oop_recorder);
+
+  _instructions = buffer.insts();
+  _constants = buffer.consts();
+
+  // copy the code into the newly created CodeBuffer
+  memcpy(_instructions->start(), _code->base(T_BYTE), _code_size);
+  _instructions->set_end(_instructions->start() + _code_size);
+
+  oop* sites = (oop*) _sites->base(T_OBJECT);
+  for (int i = 0; i < _sites->length(); i++) {
+    oop site = sites[i];
+    jint pc_offset = CiTargetMethod_Site::pcOffset(site);
+
+    if (site->is_a(CiTargetMethod_Safepoint::klass())) {
+      TRACE_graal_4("safepoint at %i", pc_offset);
+      site_Safepoint(buffer, pc_offset, site);
+    } else if (site->is_a(CiTargetMethod_Call::klass())) {
+      TRACE_graal_4("call at %i", pc_offset);
+      site_Call(buffer, pc_offset, site);
+    } else if (site->is_a(CiTargetMethod_DataPatch::klass())) {
+      TRACE_graal_4("datapatch at %i", pc_offset);
+      site_DataPatch(buffer, pc_offset, site);
+    } else if (site->is_a(CiTargetMethod_Mark::klass())) {
+      TRACE_graal_4("mark at %i", pc_offset);
+      site_Mark(buffer, pc_offset, site);
+    } else {
+      fatal("unexpected Site subclass");
+    }
+  }
+
+
+  if (_assumptions != NULL) {
+    oop* assumptions = (oop*) _assumptions->base(T_OBJECT);
+    for (int i = 0; i < _assumptions->length(); ++i) {
+      oop assumption = assumptions[i];
+      if (assumption != NULL) {
+        if (assumption->is_a(CiAssumptions_ConcreteSubtype::klass())) {
+          assumption_ConcreteSubtype(assumption);
+        } else if (assumption->is_a(CiAssumptions_ConcreteMethod::klass())) {
+          assumption_ConcreteMethod(assumption);
+        } else {
+          fatal("unexpected Assumption subclass");
+        }
+      }
+    }
+  }
+}
+
+void CodeInstaller::assumption_ConcreteSubtype(oop assumption) {
+  oop context_oop = CiAssumptions_ConcreteSubtype::context(assumption);
+  oop type_oop = CiAssumptions_ConcreteSubtype::subtype(assumption);
+
+  ciKlass* context = (ciKlass*) CURRENT_ENV->get_object(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(context_oop)));
+  ciKlass* type = (ciKlass*) CURRENT_ENV->get_object(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(type_oop)));
+
+  _dependencies->assert_leaf_type(type);
+  if (context != type) {
+    assert(context->is_abstract(), "");
+    ThreadToNativeFromVM trans(JavaThread::current());
+    _dependencies->assert_abstract_with_unique_concrete_subtype(context, type);
+  }
+}
+
+void CodeInstaller::assumption_ConcreteMethod(oop assumption) {
+  oop context_oop = CiAssumptions_ConcreteMethod::context(assumption);
+  oop method_oop = CiAssumptions_ConcreteMethod::method(assumption);
+  methodOop method = getMethodFromHotSpotMethod(method_oop);
+  methodOop context = getMethodFromHotSpotMethod(context_oop);
+
+  ciMethod* m = (ciMethod*) CURRENT_ENV->get_object(method);
+  ciMethod* c = (ciMethod*) CURRENT_ENV->get_object(context);
+  ciKlass* context_klass = c->holder();
+  {
+    ThreadToNativeFromVM trans(JavaThread::current());
+    _dependencies->assert_unique_concrete_method(context_klass, m);
+  }
+}
+
+void CodeInstaller::process_exception_handlers() {
+  // allocate some arrays for use by the collection code.
+  const int num_handlers = 5;
+  GrowableArray<intptr_t>* bcis = new GrowableArray<intptr_t> (num_handlers);
+  GrowableArray<intptr_t>* scope_depths = new GrowableArray<intptr_t> (num_handlers);
+  GrowableArray<intptr_t>* pcos = new GrowableArray<intptr_t> (num_handlers);
+
+  if (_exception_handlers != NULL) {
+    oop* exception_handlers = (oop*) _exception_handlers->base(T_OBJECT);
+    for (int i = 0; i < _exception_handlers->length(); i++) {
+      jint pc_offset = CiTargetMethod_Site::pcOffset(exception_handlers[i]);
+      int start = i;
+      while ((i + 1) < _exception_handlers->length() && CiTargetMethod_Site::pcOffset(exception_handlers[i + 1]) == pc_offset)
+        i++;
+
+      // empty the arrays
+      bcis->trunc_to(0);
+      scope_depths->trunc_to(0);
+      pcos->trunc_to(0);
+
+      for (int j = start; j <= i; j++) {
+        oop exc = exception_handlers[j];
+        jint handler_offset = CiTargetMethod_ExceptionHandler::handlerPos(exc);
+        jint handler_bci = CiTargetMethod_ExceptionHandler::handlerBci(exc);
+        jint bci = CiTargetMethod_ExceptionHandler::bci(exc);
+        jint scope_level = CiTargetMethod_ExceptionHandler::scopeLevel(exc);
+        Handle handler_type = CiTargetMethod_ExceptionHandler::exceptionType(exc);
+
+        assert(handler_offset != -1, "must have been generated");
+
+        int e = bcis->find(handler_bci);
+        if (e >= 0 && scope_depths->at(e) == scope_level) {
+          // two different handlers are declared to dispatch to the same
+          // catch bci.  During parsing we created edges for each
+          // handler but we really only need one.  The exception handler
+          // table will also get unhappy if we try to declare both since
+          // it's nonsensical.  Just skip this handler.
+          continue;
+        }
+
+        bcis->append(handler_bci);
+        if (handler_bci == -1) {
+          // insert a wildcard handler at scope depth 0 so that the
+          // exception lookup logic with find it.
+          scope_depths->append(0);
+        } else {
+          scope_depths->append(scope_level);
+        }
+        pcos->append(handler_offset);
+
+        // stop processing once we hit a catch any
+        //        if (handler->is_catch_all()) {
+        //          assert(i == handlers->length() - 1, "catch all must be last handler");
+        //        }
+
+      }
+      _exception_handler_table.add_subtable(pc_offset, bcis, scope_depths, pcos);
+    }
+  }
+
+}
+
+void CodeInstaller::record_scope(jint pc_offset, oop code_pos, GrowableArray<ScopeValue*>* objects) {
+  oop caller_pos = CiCodePos::caller(code_pos);
+  if (caller_pos != NULL) {
+    record_scope(pc_offset, caller_pos, objects);
+  }
+  oop frame = NULL;
+  if (code_pos->klass()->klass_part()->name() == vmSymbols::com_sun_cri_ci_CiFrame()) {
+    frame = code_pos;
+  }
+
+  oop hotspot_method = CiCodePos::method(code_pos);
+  methodOop method = getMethodFromHotSpotMethod(hotspot_method);
+  ciMethod *cimethod = (ciMethod *) _env->get_object(method);
+  jint bci = CiCodePos::bci(code_pos);
+  bool reexecute;
+  if (bci == -1) {
+     reexecute = false;
+  } else {
+    Bytecodes::Code code = Bytecodes::java_code_at(method, method->bcp_from(bci));
+    reexecute = Interpreter::bytecode_should_reexecute(code);
+  }
+
+  if (TraceGraal >= 2) {
+    tty->print_cr("Recording scope pc_offset=%d bci=%d frame=%d", pc_offset, bci, frame);
+  }
+
+  if (frame != NULL) {
+    jint local_count = CiFrame::numLocals(frame);
+    jint expression_count = CiFrame::numStack(frame);
+    jint monitor_count = CiFrame::numLocks(frame);
+    arrayOop values = (arrayOop) CiFrame::values(frame);
+
+    assert(local_count + expression_count + monitor_count == values->length(), "unexpected values length");
+
+    GrowableArray<ScopeValue*>* locals = new GrowableArray<ScopeValue*> ();
+    GrowableArray<ScopeValue*>* expressions = new GrowableArray<ScopeValue*> ();
+    GrowableArray<MonitorValue*>* monitors = new GrowableArray<MonitorValue*> ();
+
+    if (TraceGraal >= 2) {
+      tty->print_cr("Scope at bci %d with %d values", bci, values->length());
+      tty->print_cr("%d locals %d expressions, %d monitors", local_count, expression_count, monitor_count);
+    }
+
+    for (jint i = 0; i < values->length(); i++) {
+      ScopeValue* second = NULL;
+      ScopeValue* value = get_hotspot_value(((oop*) values->base(T_OBJECT))[i], _frame_size, objects, second);
+
+      if (i < local_count) {
+        if (second != NULL) {
+          locals->append(second);
+        }
+        locals->append(value);
+      } else if (i < local_count + expression_count) {
+        if (second != NULL) {
+          expressions->append(value);
+        }
+        expressions->append(value);
+      } else {
+        assert(second == NULL, "monitor cannot occupy two stack slots");
+        assert(value->is_location(), "invalid monitor location");
+        LocationValue* loc = (LocationValue*)value;
+        int monitor_offset = loc->location().stack_offset();
+        LocationValue* obj = new LocationValue(Location::new_stk_loc(Location::oop, monitor_offset + BasicObjectLock::obj_offset_in_bytes()));
+        monitors->append(new MonitorValue(obj, Location::new_stk_loc(Location::normal, monitor_offset  + BasicObjectLock::lock_offset_in_bytes())));
+      }
+      if (second != NULL) {
+        i++;
+        assert(i < values->length(), "double-slot value not followed by CiValue.IllegalValue");
+        assert(((oop*) values->base(T_OBJECT))[i] == CiValue::IllegalValue(), "double-slot value not followed by CiValue.IllegalValue");
+      }
+    }
+
+    _debug_recorder->dump_object_pool(objects);
+
+    DebugToken* locals_token = _debug_recorder->create_scope_values(locals);
+    DebugToken* expressions_token = _debug_recorder->create_scope_values(expressions);
+    DebugToken* monitors_token = _debug_recorder->create_monitor_values(monitors);
+
+    bool throw_exception = false;
+    if (CiFrame::rethrowException(frame)) {
+      throw_exception = true;
+    }
+
+    _debug_recorder->describe_scope(pc_offset, cimethod, bci, reexecute, throw_exception, false, false, locals_token, expressions_token, monitors_token);
+  } else {
+    _debug_recorder->describe_scope(pc_offset, cimethod, bci, reexecute, false, false, false, NULL, NULL, NULL);
+  }
+}
+
+void CodeInstaller::site_Safepoint(CodeBuffer& buffer, jint pc_offset, oop site) {
+  oop debug_info = CiTargetMethod_Safepoint::debugInfo(site);
+  assert(debug_info != NULL, "debug info expected");
+
+  // address instruction = _instructions->start() + pc_offset;
+  // jint next_pc_offset = Assembler::locate_next_instruction(instruction) - _instructions->start();
+  _debug_recorder->add_safepoint(pc_offset, create_oop_map(_frame_size, _parameter_count, debug_info));
+
+  oop code_pos = CiDebugInfo::codePos(debug_info);
+  record_scope(pc_offset, code_pos, new GrowableArray<ScopeValue*>());
+
+  _debug_recorder->end_safepoint(pc_offset);
+}
+
+void CodeInstaller::site_Call(CodeBuffer& buffer, jint pc_offset, oop site) {
+  oop runtime_call = CiTargetMethod_Call::runtimeCall(site);
+  oop hotspot_method = CiTargetMethod_Call::method(site);
+  oop symbol = CiTargetMethod_Call::symbol(site);
+  oop global_stub = CiTargetMethod_Call::stubID(site);
+
+  oop debug_info = CiTargetMethod_Call::debugInfo(site);
+
+  assert((runtime_call ? 1 : 0) + (hotspot_method ? 1 : 0) + (symbol ? 1 : 0) + (global_stub ? 1 : 0) == 1, "Call site needs exactly one type");
+
+  assert(NativeCall::instruction_size == (int)NativeJump::instruction_size, "unexpected size)");
+  jint next_pc_offset = pc_offset + NativeCall::instruction_size;
+
+  if (debug_info != NULL) {
+    _debug_recorder->add_safepoint(next_pc_offset, create_oop_map(_frame_size, _parameter_count, debug_info));
+    oop code_pos = CiDebugInfo::codePos(debug_info);
+    record_scope(next_pc_offset, code_pos, new GrowableArray<ScopeValue*>());
+  }
+
+  if (runtime_call != NULL) {
+    NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+    if (runtime_call == CiRuntimeCall::Debug()) {
+      TRACE_graal_3("CiRuntimeCall::Debug()");
+    } else if (runtime_call == CiRuntimeCall::UnwindException()) {
+      call->set_destination(Runtime1::entry_for(Runtime1::graal_unwind_exception_call_id));
+      _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
+      TRACE_graal_3("CiRuntimeCall::UnwindException()");
+    } else if (runtime_call == CiRuntimeCall::HandleException()) {
+      call->set_destination(Runtime1::entry_for(Runtime1::graal_handle_exception_id));
+      _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
+      TRACE_graal_3("CiRuntimeCall::HandleException()");
+    } else if (runtime_call == CiRuntimeCall::JavaTimeMillis()) {
+      call->set_destination((address)os::javaTimeMillis);
+      _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
+      TRACE_graal_3("CiRuntimeCall::JavaTimeMillis()");
+    } else if (runtime_call == CiRuntimeCall::JavaTimeNanos()) {
+      call->set_destination((address)os::javaTimeNanos);
+      _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
+      TRACE_graal_3("CiRuntimeCall::JavaTimeNanos()");
+    } else if (runtime_call == CiRuntimeCall::ArithmeticFrem()) {
+      call->set_destination(Runtime1::entry_for(Runtime1::graal_arithmetic_frem_id));
+      _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
+      TRACE_graal_3("CiRuntimeCall::ArithmeticFrem()");
+    } else if (runtime_call == CiRuntimeCall::ArithmeticDrem()) {
+      call->set_destination(Runtime1::entry_for(Runtime1::graal_arithmetic_drem_id));
+      _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
+      TRACE_graal_3("CiRuntimeCall::ArithmeticDrem()");
+    } else if (runtime_call == CiRuntimeCall::RegisterFinalizer()) {
+      call->set_destination(Runtime1::entry_for(Runtime1::register_finalizer_id));
+      _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
+    } else if (runtime_call == CiRuntimeCall::Deoptimize()) {
+      call->set_destination(SharedRuntime::deopt_blob()->uncommon_trap());
+      _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
+    } else {
+      runtime_call->print();
+      fatal("runtime_call not implemented");
+    }
+  } else if (global_stub != NULL) {
+    NativeInstruction* inst = nativeInstruction_at(_instructions->start() + pc_offset);
+    assert(java_lang_boxing_object::is_instance(global_stub, T_LONG), "global_stub needs to be of type Long");
+
+    if (inst->is_call()) {
+      nativeCall_at((address)inst)->set_destination(VmIds::getStub(global_stub));
+    } else {
+      nativeJump_at((address)inst)->set_jump_destination(VmIds::getStub(global_stub));
+    }
+    _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand);
+    TRACE_graal_3("relocating (stub)  at %016x", inst);
+  } else if (symbol != NULL) {
+    fatal("symbol");
+  } else { // method != NULL
+    NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+    assert(hotspot_method != NULL, "unexpected RiMethod");
+    assert(debug_info != NULL, "debug info expected");
+
+    methodOop method = NULL;
+    // we need to check, this might also be an unresolved method
+    if (hotspot_method->is_a(HotSpotMethodResolved::klass())) {
+      method = getMethodFromHotSpotMethod(hotspot_method);
+    }
+
+    assert(debug_info != NULL, "debug info expected");
+
+    TRACE_graal_3("method call");
+    switch (_next_call_type) {
+      case MARK_INVOKEVIRTUAL:
+      case MARK_INVOKEINTERFACE: {
+        assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface");
+
+        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 MARK_INVOKESTATIC: {
+        assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic");
+        call->set_destination(SharedRuntime::get_resolve_static_call_stub());
+        _instructions->relocate(call->instruction_address(), relocInfo::static_call_type, Assembler::call32_operand);
+        break;
+      }
+      case MARK_INVOKESPECIAL: {
+        assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial");
+
+        call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub());
+        _instructions->relocate(call->instruction_address(), relocInfo::opt_virtual_call_type, Assembler::call32_operand);
+        break;
+      }
+      case MARK_INVOKE_INVALID:
+      default:
+        fatal("invalid _next_call_type value");
+        break;
+    }
+  }
+  _next_call_type = MARK_INVOKE_INVALID;
+  if (debug_info != NULL) {
+    _debug_recorder->end_safepoint(next_pc_offset);
+  }
+}
+
+void CodeInstaller::site_DataPatch(CodeBuffer& buffer, jint pc_offset, oop site) {
+  oop constant = CiTargetMethod_DataPatch::constant(site);
+  oop kind = CiConstant::kind(constant);
+
+  address instruction = _instructions->start() + pc_offset;
+
+  char typeChar = CiKind::typeChar(kind);
+  switch (typeChar) {
+    case 'z':
+    case 'b':
+    case 's':
+    case 'c':
+    case 'i':
+      fatal("int-sized values not expected in DataPatch")
+      ;
+      break;
+    case 'f':
+    case 'l':
+    case 'd': {
+      address operand = Assembler::locate_operand(instruction, Assembler::disp32_operand);
+      address next_instruction = Assembler::locate_next_instruction(instruction);
+      // we don't care if this is a long/double/etc., the primitive field contains the right bits
+      int size = _constants->size();
+      if (typeChar == 'd' || typeChar == 'l') {
+        size = _constants->align_at_start(size);
+      }
+      address dest = _constants->start() + size;
+      _constants->set_end(dest + BytesPerLong);
+      *(jlong*) dest = CiConstant::primitive(constant);
+
+      long disp = dest - next_instruction;
+      assert(disp == (jint) disp, "disp doesn't fit in 32 bits");
+      *((jint*) operand) = (jint) disp;
+
+      _instructions->relocate(instruction, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS), Assembler::disp32_operand);
+      TRACE_graal_3("relocating (%c) at %016x/%016x with destination at %016x (%d)", typeChar, instruction, operand, dest, size);
+      break;
+    }
+    case 'a': {
+      address operand = Assembler::locate_operand(instruction, Assembler::imm_operand);
+      Handle obj = CiConstant::object(constant);
+
+      if (obj->is_a(HotSpotTypeResolved::klass())) {
+        assert(!obj.is_null(), "");
+        *((jobject*) operand) = JNIHandles::make_local(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(obj)));
+        _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand);
+        TRACE_graal_3("relocating (HotSpotType) at %016x/%016x", instruction, operand);
+      } else {
+        jobject value;
+        if (obj() == HotSpotProxy::DUMMY_CONSTANT_OBJ()) {
+          value = (jobject) Universe::non_oop_word();
+        } else {
+          value = JNIHandles::make_local(obj());
+        }
+        *((jobject*) operand) = value;
+        _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand);
+        TRACE_graal_3("relocating (oop constant) at %016x/%016x", instruction, operand);
+      }
+      break;
+    }
+    default:
+      fatal("unexpected CiKind in DataPatch");
+      break;
+  }
+}
+
+void CodeInstaller::site_Mark(CodeBuffer& buffer, jint pc_offset, oop site) {
+  oop id_obj = CiTargetMethod_Mark::id(site);
+  arrayOop references = (arrayOop) CiTargetMethod_Mark::references(site);
+
+  if (id_obj != NULL) {
+    assert(java_lang_boxing_object::is_instance(id_obj, T_INT), "Integer id expected");
+    jint id = id_obj->int_field(java_lang_boxing_object::value_offset_in_bytes(T_INT));
+
+    address instruction = _instructions->start() + pc_offset;
+
+    switch (id) {
+      case MARK_UNVERIFIED_ENTRY:
+        _offsets.set_value(CodeOffsets::Entry, pc_offset);
+        break;
+      case MARK_VERIFIED_ENTRY:
+        _offsets.set_value(CodeOffsets::Verified_Entry, pc_offset);
+        break;
+      case MARK_OSR_ENTRY:
+        _offsets.set_value(CodeOffsets::OSR_Entry, pc_offset);
+        break;
+      case MARK_UNWIND_ENTRY:
+        _offsets.set_value(CodeOffsets::UnwindHandler, pc_offset);
+        break;
+      case MARK_EXCEPTION_HANDLER_ENTRY:
+        _offsets.set_value(CodeOffsets::Exceptions, pc_offset);
+        break;
+      case MARK_DEOPT_HANDLER_ENTRY:
+        _offsets.set_value(CodeOffsets::Deopt, pc_offset);
+        break;
+      case MARK_STATIC_CALL_STUB: {
+        assert(references->length() == 1, "static call stub needs one reference");
+        oop ref = ((oop*) references->base(T_OBJECT))[0];
+        address call_pc = _instructions->start() + CiTargetMethod_Site::pcOffset(ref);
+        _instructions->relocate(instruction, static_stub_Relocation::spec(call_pc));
+        _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand);
+        break;
+      }
+      case MARK_INVOKE_INVALID:
+      case MARK_INVOKEINTERFACE:
+      case MARK_INVOKESTATIC:
+      case MARK_INVOKESPECIAL:
+      case MARK_INVOKEVIRTUAL:
+        _next_call_type = (MarkId) id;
+        _invoke_mark_pc = instruction;
+        break;
+      case MARK_IMPLICIT_NULL:
+        _implicit_exception_table.append(pc_offset, pc_offset);
+        break;
+      case MARK_KLASS_PATCHING:
+      case MARK_ACCESS_FIELD_PATCHING: {
+        unsigned char* byte_count = (unsigned char*) (instruction - 1);
+        unsigned char* byte_skip = (unsigned char*) (instruction - 2);
+        unsigned char* being_initialized_entry_offset = (unsigned char*) (instruction - 3);
+
+        assert(*byte_skip == 5, "unexpected byte_skip");
+
+        assert(references->length() == 2, "MARK_KLASS_PATCHING/MARK_ACCESS_FIELD_PATCHING needs 2 references");
+        oop ref1 = ((oop*) references->base(T_OBJECT))[0];
+        oop ref2 = ((oop*) references->base(T_OBJECT))[1];
+        int i_byte_count = CiTargetMethod_Site::pcOffset(ref2) - CiTargetMethod_Site::pcOffset(ref1);
+        assert(i_byte_count == (unsigned char)i_byte_count, "invalid offset");
+        *byte_count = i_byte_count;
+        *being_initialized_entry_offset = *byte_count + *byte_skip;
+
+        // we need to correct the offset of a field access - it's created with MAX_INT to ensure the correct size, and hotspot expects 0
+        if (id == MARK_ACCESS_FIELD_PATCHING) {
+          NativeMovRegMem* inst = nativeMovRegMem_at(_instructions->start() + CiTargetMethod_Site::pcOffset(ref1));
+          assert(inst->offset() == max_jint, "unexpected offset value");
+          inst->set_offset(0);
+        }
+        break;
+      }
+      case MARK_DUMMY_OOP_RELOCATION: {
+        _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand);
+
+        RelocIterator iter(_instructions, (address) instruction, (address) (instruction + 1));
+        relocInfo::change_reloc_info_for_address(&iter, (address) instruction, relocInfo::oop_type, relocInfo::none);
+        break;
+      }
+      default:
+        ShouldNotReachHere();
+        break;
+    }
+  }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/graal/graalCodeInstaller.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,106 @@
+/*
+ * 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.
+ */
+
+/*
+ * This class handles the conversion from a CiTargetMethod to a CodeBlob or an nmethod.
+ */
+class CodeInstaller {
+private:
+  // these need to correspond to HotSpotXirGenerator.java
+  enum MarkId {
+    MARK_VERIFIED_ENTRY             = 0x0001,
+    MARK_UNVERIFIED_ENTRY           = 0x0002,
+    MARK_OSR_ENTRY                  = 0x0003,
+    MARK_UNWIND_ENTRY               = 0x0004,
+    MARK_EXCEPTION_HANDLER_ENTRY    = 0x0005,
+    MARK_DEOPT_HANDLER_ENTRY        = 0x0006,
+    MARK_STATIC_CALL_STUB           = 0x1000,
+    MARK_INVOKE_INVALID             = 0x2000,
+    MARK_INVOKEINTERFACE            = 0x2001,
+    MARK_INVOKESTATIC               = 0x2002,
+    MARK_INVOKESPECIAL              = 0x2003,
+    MARK_INVOKEVIRTUAL              = 0x2004,
+    MARK_IMPLICIT_NULL              = 0x3000,
+    MARK_KLASS_PATCHING             = 0x4000,
+    MARK_DUMMY_OOP_RELOCATION       = 0x4001,
+    MARK_ACCESS_FIELD_PATCHING      = 0x4002
+  };
+
+  ciEnv*        _env;
+
+  oop           _citarget_method;
+  oop           _hotspot_method;
+  oop           _name;
+  arrayOop      _sites;
+  arrayOop      _assumptions;
+  arrayOop      _exception_handlers;
+  CodeOffsets   _offsets;
+
+  arrayOop      _code;
+  jint          _code_size;
+  jint          _frame_size;
+  jint          _custom_stack_area_offset;
+  jint          _parameter_count;
+  jint          _constants_size;
+  jint          _total_size;
+
+  MarkId        _next_call_type;
+  address       _invoke_mark_pc;
+
+  CodeSection*  _instructions;
+  CodeSection*  _constants;
+
+  OopRecorder*              _oop_recorder;
+  DebugInformationRecorder* _debug_recorder;
+  Dependencies*             _dependencies;
+  ExceptionHandlerTable     _exception_handler_table;
+  ImplicitExceptionTable    _implicit_exception_table;
+
+public:
+
+  // constructor used to create a method
+  CodeInstaller(Handle target_method);
+
+  // constructor used to create a stub
+  CodeInstaller(Handle target_method, jlong& id);
+
+private:
+  // extract the fields of the CiTargetMethod
+  void initialize_fields(Handle target_method);
+
+  // perform data and call relocation on the CodeBuffer
+  void initialize_buffer(CodeBuffer& buffer);
+
+  void assumption_ConcreteSubtype(oop assumption);
+  void assumption_ConcreteMethod(oop assumption);
+
+  void site_Safepoint(CodeBuffer& buffer, jint pc_offset, oop site);
+  void site_Call(CodeBuffer& buffer, jint pc_offset, oop site);
+  void site_DataPatch(CodeBuffer& buffer, jint pc_offset, oop site);
+  void site_Mark(CodeBuffer& buffer, jint pc_offset, oop site);
+
+  void record_scope(jint pc_offset, oop code_pos, GrowableArray<ScopeValue*>* objects);
+
+  void process_exception_handlers();
+
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/graal/graalCompiler.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -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.
+ */
+
+#include "precompiled.hpp"
+#include "graal/graalCompiler.hpp"
+#include "graal/graalJavaAccess.hpp"
+#include "graal/graalVMExits.hpp"
+#include "graal/graalVMEntries.hpp"
+#include "graal/graalVmIds.hpp"
+#include "c1/c1_Runtime1.hpp"
+#include "runtime/arguments.hpp"
+
+GraalCompiler* GraalCompiler::_instance = NULL;
+
+GraalCompiler::GraalCompiler() {
+  _initialized = false;
+  assert(_instance == NULL, "only one instance allowed");
+  _instance = this;
+}
+
+// Initialization
+void GraalCompiler::initialize() {
+  if (_initialized) return;
+  _initialized = true;
+  CompilerThread* THREAD = CompilerThread::current();
+  TRACE_graal_1("GraalCompiler::initialize");
+
+  VmIds::initializeObjects();
+
+  initialize_buffer_blob();
+  Runtime1::initialize(THREAD->get_buffer_blob());
+
+  JNIEnv *env = ((JavaThread *) Thread::current())->jni_environment();
+  jclass klass = env->FindClass("com/oracle/max/graal/runtime/VMEntriesNative");
+  if (klass == NULL) {
+    tty->print_cr("graal VMEntries class not found");
+    vm_abort(false);
+  }
+  env->RegisterNatives(klass, VMEntries_methods, VMEntries_methods_count());
+
+  {
+    VM_ENTRY_MARK;
+    check_pending_exception("Could not register natives");
+  }
+
+  graal_compute_offsets();
+
+  {
+    VM_ENTRY_MARK;
+    HandleMark hm;
+    VMExits::initializeCompiler();
+    VMExits::setDefaultOptions();
+    for (int i = 0; i < Arguments::num_graal_args(); ++i) {
+      const char* arg = Arguments::graal_args_array()[i];
+      Handle option = java_lang_String::create_from_str(arg, THREAD);
+      jboolean result = VMExits::setOption(option);
+      if (!result) {
+        tty->print_cr("Invalid option for graal!");
+        vm_abort(false);
+      }
+    }
+  }
+}
+
+void GraalCompiler::initialize_buffer_blob() {
+
+  CompilerThread* THREAD = CompilerThread::current();
+  if (THREAD->get_buffer_blob() == NULL) {
+    // setup CodeBuffer.  Preallocate a BufferBlob of size
+    // NMethodSizeLimit plus some extra space for constants.
+    int code_buffer_size = Compilation::desired_max_code_buffer_size() +
+      Compilation::desired_max_constant_size();
+    BufferBlob* blob = BufferBlob::create("graal temporary CodeBuffer",
+                                          code_buffer_size);
+    guarantee(blob != NULL, "must create code buffer");
+    THREAD->set_buffer_blob(blob);
+  }
+}
+
+// Compilation entry point for methods
+void GraalCompiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci) {
+  assert(_initialized, "must already be initialized");
+  VM_ENTRY_MARK;
+  ResourceMark rm;
+  HandleMark hm;
+
+  initialize_buffer_blob();
+  VmIds::initializeObjects();
+
+  TRACE_graal_2("GraalCompiler::compile_method");
+
+  CompilerThread::current()->set_compiling(true);
+  methodOop method = (methodOop) target->get_oop();
+  Handle name = VmIds::toString<Handle>(method->name(), CHECK);
+  Handle hotspot_method = GraalCompiler::createHotSpotMethodResolved(method, name, CHECK);
+  VMExits::compileMethod(hotspot_method, entry_bci);
+  CompilerThread::current()->set_compiling(false);
+
+  VmIds::cleanupLocalObjects();
+  TRACE_graal_2("GraalCompiler::compile_method exit");
+}
+
+void GraalCompiler::exit() {
+  VMExits::shutdownCompiler();
+}
+
+// Print compilation timers and statistics
+void GraalCompiler::print_timers() {
+  TRACE_graal_1("GraalCompiler::print_timers");
+}
+
+oop GraalCompiler::get_RiType(ciType *type, KlassHandle accessor, TRAPS) {
+  if (type->is_loaded()) {
+    if (type->is_primitive_type()) {
+      return VMExits::createRiTypePrimitive((int) type->basic_type(), THREAD);
+    }
+    KlassHandle klass = (klassOop) type->get_oop();
+    Handle name = VmIds::toString<Handle>(klass->name(), THREAD);
+    return createHotSpotTypeResolved(klass, name, CHECK_NULL);
+  } else {
+    Symbol* name = ((ciKlass *) type)->name()->get_symbol();
+    return VMExits::createRiTypeUnresolved(VmIds::toString<Handle>(name, THREAD), THREAD);
+  }
+}
+
+oop GraalCompiler::get_RiField(ciField *field, ciInstanceKlass* accessor_klass, KlassHandle accessor, Bytecodes::Code byteCode, TRAPS) {
+  int offset;
+  if (byteCode != Bytecodes::_illegal) {
+    bool will_link = field->will_link_from_vm(accessor_klass, byteCode);
+    offset = (field->holder()->is_loaded() && will_link) ? field->offset() : -1;
+  } else {
+    offset = field->offset();
+  }
+  Handle field_name = VmIds::toString<Handle>(field->name()->get_symbol(), CHECK_0);
+  Handle field_holder = get_RiType(field->holder(), accessor, CHECK_0);
+  Handle field_type = get_RiType(field->type(), accessor, CHECK_0);
+  int flags = field->flags().as_int();
+  return VMExits::createRiField(field_holder, field_name, field_type, offset, flags, THREAD);
+}
+
+oop GraalCompiler::createHotSpotTypeResolved(KlassHandle klass, Handle name, TRAPS) {
+  if (klass->graal_mirror() != NULL) {
+    return klass->graal_mirror();
+  }
+
+  instanceKlass::cast(HotSpotTypeResolved::klass())->initialize(CHECK_NULL);
+  Handle obj = instanceKlass::cast(HotSpotTypeResolved::klass())->allocate_instance(CHECK_NULL);
+  assert(obj() != NULL, "must succeed in allocating instance");
+
+  HotSpotTypeResolved::set_compiler(obj, VMExits::compilerInstance()());
+
+  if (klass->oop_is_instance()) {
+    instanceKlass* ik = (instanceKlass*)klass()->klass_part();
+    Handle full_name = java_lang_String::create_from_str(ik->signature_name(), CHECK_NULL);
+    HotSpotType::set_name(obj, full_name());
+  } else {
+    HotSpotType::set_name(obj, name());
+  }
+
+  HotSpotTypeResolved::set_javaMirror(obj, klass->java_mirror());
+  HotSpotTypeResolved::set_simpleName(obj, name());
+  HotSpotTypeResolved::set_accessFlags(obj, klass->access_flags().as_int());
+  HotSpotTypeResolved::set_isInterface(obj, klass->is_interface());
+  HotSpotTypeResolved::set_isInstanceClass(obj, klass->oop_is_instance());
+
+  if (klass->oop_is_javaArray()) {
+    HotSpotTypeResolved::set_isArrayClass(obj, true);
+    HotSpotTypeResolved::set_componentType(obj, NULL);
+  } else {
+    HotSpotTypeResolved::set_isArrayClass(obj, false);
+    HotSpotTypeResolved::set_componentType(obj, NULL);
+    HotSpotTypeResolved::set_instanceSize(obj, instanceKlass::cast(klass())->size_helper() * HeapWordSize);
+    HotSpotTypeResolved::set_hasFinalizer(obj, klass->has_finalizer());
+  }
+
+  // TODO replace these with correct values
+  HotSpotTypeResolved::set_hasSubclass(obj, false);
+  HotSpotTypeResolved::set_hasFinalizableSubclass(obj, false);
+
+  klass->set_graal_mirror(obj());
+
+  return obj();
+}
+
+oop GraalCompiler::createHotSpotMethodResolved(methodHandle method, Handle name, TRAPS) {
+  if (method->graal_mirror() != NULL) {
+    assert(method->graal_mirror()->is_a(HotSpotMethodResolved::klass()), "unexpected class...");
+    return method->graal_mirror();
+  }
+
+  instanceKlass::cast(HotSpotMethodResolved::klass())->initialize(CHECK_NULL);
+  Handle obj = instanceKlass::cast(HotSpotMethodResolved::klass())->allocate_instance(CHECK_NULL);
+  assert(obj() != NULL, "must succeed in allocating instance");
+  
+  HotSpotMethodResolved::set_compiler(obj, VMExits::compilerInstance()());
+  // (tw) Cannot use reflection here, because the compiler thread could dead lock with the running application.
+  // oop reflected = getReflectedMethod(method(), CHECK_NULL);
+  HotSpotMethodResolved::set_javaMirror(obj, method());
+  HotSpotMethodResolved::set_name(obj, name());
+  
+  KlassHandle klass = method->method_holder();
+  Handle holder_name = VmIds::toString<Handle>(klass->name(), CHECK_NULL);
+  oop holder = GraalCompiler::createHotSpotTypeResolved(klass, holder_name, CHECK_NULL);
+  HotSpotMethodResolved::set_holder(obj, holder);
+  
+  HotSpotMethodResolved::set_codeSize(obj, method->code_size());
+  HotSpotMethodResolved::set_accessFlags(obj, method->access_flags().as_int());
+  HotSpotMethodResolved::set_maxLocals(obj, method->max_locals());
+  HotSpotMethodResolved::set_maxStackSize(obj, method->max_stack());
+  
+  method->set_graal_mirror(obj());
+  return obj();
+}
+
+BasicType GraalCompiler::kindToBasicType(jchar ch) {
+  switch(ch) {
+    case 'z': return T_BOOLEAN;
+    case 'b': return T_BYTE;
+    case 's': return T_SHORT;
+    case 'c': return T_CHAR;
+    case 'i': return T_INT;
+    case 'f': return T_FLOAT;
+    case 'l': return T_LONG;
+    case 'd': return T_DOUBLE;
+    case 'a': return T_OBJECT;
+    case 'r': return T_ADDRESS;
+    case '-': return T_ILLEGAL;
+    default:
+      fatal(err_msg("unexpected CiKind: %c", ch));
+      break;
+  }
+  return T_ILLEGAL;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/graal/graalCompiler.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "compiler/abstractCompiler.hpp"
+
+class GraalCompiler : public AbstractCompiler {
+
+private:
+
+  bool                  _initialized;
+
+  static GraalCompiler*   _instance;
+
+public:
+
+  GraalCompiler();
+
+  static GraalCompiler* instance() { return _instance; }
+
+
+  virtual const char* name() { return "G"; }
+
+  // Native / OSR not supported
+  virtual bool supports_native()                 { return false; }
+  virtual bool supports_osr   ()                 { return false; }
+
+  // Pretend to be C1
+  bool is_c1   ()                                { return true; }
+  bool is_c2   ()                                { return false; }
+
+  // Initialization
+  virtual void initialize();
+
+  // Compilation entry point for methods
+  virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci);
+
+  // Print compilation timers and statistics
+  virtual void print_timers();
+
+  static oop get_RiType(ciType *klass, KlassHandle accessor, TRAPS);
+  static oop get_RiField(ciField *ciField, ciInstanceKlass* accessor_klass, KlassHandle accessor, Bytecodes::Code byteCode, TRAPS);
+
+  static oop createHotSpotTypeResolved(KlassHandle klass, Handle name, TRAPS);
+  static oop createHotSpotMethodResolved(methodHandle method, Handle name, TRAPS);
+
+  void exit();
+
+  static BasicType kindToBasicType(jchar ch);
+
+  static int to_cp_index_u2(int index) {
+    // Swap.
+    index = ((index & 0xFF) << 8) | (index >> 8);
+    // Tag.
+    index = index + constantPoolOopDesc::CPCACHE_INDEX_TAG;
+    return index;
+  }
+
+private:
+
+  void initialize_buffer_blob();
+};
+
+// Tracing macros
+
+#define IF_TRACE_graal_1 if (!(TraceGraal >= 1)) ; else
+#define IF_TRACE_graal_2 if (!(TraceGraal >= 2)) ; else
+#define IF_TRACE_graal_3 if (!(TraceGraal >= 3)) ; else
+#define IF_TRACE_graal_4 if (!(TraceGraal >= 4)) ; else
+#define IF_TRACE_graal_5 if (!(TraceGraal >= 5)) ; else
+
+// using commas and else to keep one-instruction semantics
+
+#define TRACE_graal_1 if (!(TraceGraal >= 1 && (tty->print("TraceGraal-1: "), true))) ; else tty->print_cr
+#define TRACE_graal_2 if (!(TraceGraal >= 2 && (tty->print("   TraceGraal-2: "), true))) ; else tty->print_cr
+#define TRACE_graal_3 if (!(TraceGraal >= 3 && (tty->print("      TraceGraal-3: "), true))) ; else tty->print_cr
+#define TRACE_graal_4 if (!(TraceGraal >= 4 && (tty->print("         TraceGraal-4: "), true))) ; else tty->print_cr
+#define TRACE_graal_5 if (!(TraceGraal >= 5 && (tty->print("            TraceGraal-5: "), true))) ; else tty->print_cr
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/graal/graalJavaAccess.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+
+#include "precompiled.hpp"
+#include "graal/graalJavaAccess.hpp"
+#include "runtime/jniHandles.hpp"
+#include "classfile/symbolTable.hpp"
+// This function is similar to javaClasses.cpp, it computes the field offset of a (static or instance) field.
+// It looks up the name and signature symbols without creating new ones, all the symbols of these classes need to be already loaded.
+
+static void compute_offset(int &dest_offset, klassOop klass_oop, const char* name, const char* signature, bool static_field) {
+  Symbol* name_symbol = SymbolTable::probe(name, (int)strlen(name));
+  Symbol* signature_symbol = SymbolTable::probe(signature, (int)strlen(signature));
+#ifdef DEBUG
+  if (name_symbol == NULL) {
+    tty->print_cr("symbol with name %s was not found in symbol table (klass=%s)", name, klass_oop->klass_part()->name()->as_C_string());
+  }
+#endif
+  assert(name_symbol != NULL, "symbol not found - class layout changed?");
+  assert(signature_symbol != NULL, "symbol not found - class layout changed?");
+
+  instanceKlass* ik = instanceKlass::cast(klass_oop);
+  fieldDescriptor fd;
+  if (!ik->find_field(name_symbol, signature_symbol, &fd)) {
+    ResourceMark rm;
+    tty->print_cr("Invalid layout of %s at %s", name_symbol->as_C_string(), ik->external_name());
+    fatal("Invalid layout of preloaded class");
+  }
+  assert(fd.is_static() == static_field, "static/instance mismatch");
+  dest_offset = fd.offset();
+}
+
+// This piece of macro magic creates the contents of the graal_compute_offsets method that initializes the field indices of all the access classes.
+
+#define START_CLASS(name) { klassOop k = SystemDictionary::name##_klass(); assert(k != NULL, "Could not find class " #name "");
+
+#define END_CLASS }
+
+#define FIELD(klass, name, signature, static_field) compute_offset(klass::_##name##_offset, k, #name, signature, static_field);
+#define CHAR_FIELD(klass, name) FIELD(klass, name, "C", false)
+#define INT_FIELD(klass, name) FIELD(klass, name, "I", false)
+#define BOOLEAN_FIELD(klass, name) FIELD(klass, name, "Z", false)
+#define LONG_FIELD(klass, name) FIELD(klass, name, "J", false)
+#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)
+
+
+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)
+}
+
+#define EMPTY0
+#define EMPTY1(x)
+#define EMPTY2(x,y)
+#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)
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,281 @@
+/*
+ * 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.
+ */
+
+void graal_compute_offsets();
+
+#include "classfile/systemDictionary.hpp"
+#include "oops/instanceMirrorKlass.hpp"
+
+/* This macro defines the structure of the CiTargetMethod - classes.
+ * It will generate classes with accessors similar to javaClasses.hpp, but with specializations for oops, Handles and jni handles.
+ *
+ * The public interface of these classes will look like this:
+
+ * class CiStackSlot : AllStatic {
+ * public:
+ *   static klassOop klass();
+ *   static jint  index(oop obj);
+ *   static jint  index(Handle obj);
+ *   static jint  index(jobject obj);
+ *   static void set_index(oop obj, jint x);
+ *   static void set_index(Handle obj, jint x);
+ *   static void set_index(jobject obj, jint x);
+ * };
+ *
+ */
+
+#define COMPILER_CLASSES_DO(start_class, end_class, char_field, int_field, boolean_field, long_field, float_field, oop_field, static_oop_field)   \
+  start_class(HotSpotTypeResolved)                                                      \
+    oop_field(HotSpotTypeResolved, compiler, "Lcom/oracle/max/graal/runtime/Compiler;") \
+    oop_field(HotSpotTypeResolved, javaMirror, "Ljava/lang/Class;")                     \
+    oop_field(HotSpotTypeResolved, simpleName, "Ljava/lang/String;")                    \
+    int_field(HotSpotTypeResolved, accessFlags)                                         \
+    boolean_field(HotSpotTypeResolved, hasFinalizer)                                    \
+    boolean_field(HotSpotTypeResolved, hasSubclass)                                     \
+    boolean_field(HotSpotTypeResolved, hasFinalizableSubclass)                          \
+    boolean_field(HotSpotTypeResolved, isArrayClass)                                    \
+    boolean_field(HotSpotTypeResolved, isInstanceClass)                                 \
+    boolean_field(HotSpotTypeResolved, isInterface)                                     \
+    int_field(HotSpotTypeResolved, instanceSize)                                        \
+    oop_field(HotSpotTypeResolved, componentType, "Lcom/sun/cri/ri/RiType;")            \
+  end_class                                                                             \
+  start_class(HotSpotMethodResolved)                                                    \
+    oop_field(HotSpotMethodResolved, compiler, "Lcom/oracle/max/graal/runtime/Compiler;") \
+    oop_field(HotSpotMethodResolved, name, "Ljava/lang/String;")                        \
+    oop_field(HotSpotMethodResolved, holder, "Lcom/sun/cri/ri/RiType;")                 \
+    oop_field(HotSpotMethodResolved, javaMirror, "Ljava/lang/Object;")                  \
+    int_field(HotSpotMethodResolved, codeSize)                                          \
+    int_field(HotSpotMethodResolved, accessFlags)                                       \
+    int_field(HotSpotMethodResolved, maxLocals)                                         \
+    int_field(HotSpotMethodResolved, maxStackSize)                                      \
+  end_class                                                                             \
+  start_class(HotSpotType)                                                              \
+    oop_field(HotSpotType, name, "Ljava/lang/String;")                                  \
+  end_class                                                                             \
+  start_class(HotSpotField)                                                             \
+    oop_field(HotSpotField, constant, "Lcom/sun/cri/ci/CiConstant;")                    \
+  end_class                                                                             \
+  start_class(HotSpotProxy)                                                             \
+    static_oop_field(HotSpotProxy, DUMMY_CONSTANT_OBJ, "Ljava/lang/Long;")              \
+  end_class                                                                             \
+  start_class(HotSpotTargetMethod)                                                      \
+    oop_field(HotSpotTargetMethod, targetMethod, "Lcom/sun/cri/ci/CiTargetMethod;")     \
+    oop_field(HotSpotTargetMethod, method, "Lcom/oracle/max/graal/runtime/HotSpotMethodResolved;") \
+    oop_field(HotSpotTargetMethod, name, "Ljava/lang/String;")                          \
+    oop_field(HotSpotTargetMethod, sites, "[Lcom/sun/cri/ci/CiTargetMethod$Site;")      \
+    oop_field(HotSpotTargetMethod, exceptionHandlers, "[Lcom/sun/cri/ci/CiTargetMethod$ExceptionHandler;") \
+  end_class                                                                             \
+  start_class(HotSpotExceptionHandler)                                                  \
+    int_field(HotSpotExceptionHandler, startBci)                                        \
+    int_field(HotSpotExceptionHandler, endBci)                                          \
+    int_field(HotSpotExceptionHandler, handlerBci)                                      \
+    int_field(HotSpotExceptionHandler, catchClassIndex)                                 \
+    oop_field(HotSpotExceptionHandler, catchClass, "Lcom/sun/cri/ri/RiType;")           \
+  end_class                                                                             \
+  start_class(CiTargetMethod)                                                           \
+    int_field(CiTargetMethod, frameSize)                                                \
+    int_field(CiTargetMethod, customStackAreaOffset)                                    \
+    oop_field(CiTargetMethod, targetCode, "[B")                                         \
+    oop_field(CiTargetMethod, assumptions, "Lcom/sun/cri/ci/CiAssumptions;")            \
+    int_field(CiTargetMethod, targetCodeSize)                                           \
+  end_class                                                                             \
+  start_class(CiAssumptions)                                                            \
+    oop_field(CiAssumptions, list, "[Lcom/sun/cri/ci/CiAssumptions$Assumption;")        \
+  end_class                                                                             \
+  start_class(CiAssumptions_ConcreteSubtype)                                            \
+    oop_field(CiAssumptions_ConcreteSubtype, context, "Lcom/sun/cri/ri/RiType;")        \
+    oop_field(CiAssumptions_ConcreteSubtype, subtype, "Lcom/sun/cri/ri/RiType;")        \
+  end_class                                                                             \
+  start_class(CiAssumptions_ConcreteMethod)                                             \
+    oop_field(CiAssumptions_ConcreteMethod, context, "Lcom/sun/cri/ri/RiMethod;")       \
+    oop_field(CiAssumptions_ConcreteMethod, method, "Lcom/sun/cri/ri/RiMethod;")        \
+  end_class                                                                             \
+  start_class(CiTargetMethod_Site)                                                      \
+    int_field(CiTargetMethod_Site, pcOffset)                                            \
+  end_class                                                                             \
+  start_class(CiTargetMethod_Call)                                                      \
+    oop_field(CiTargetMethod_Call, runtimeCall, "Lcom/sun/cri/ci/CiRuntimeCall;")       \
+    oop_field(CiTargetMethod_Call, method, "Lcom/sun/cri/ri/RiMethod;")                 \
+    oop_field(CiTargetMethod_Call, symbol, "Ljava/lang/String;")                        \
+    oop_field(CiTargetMethod_Call, stubID, "Ljava/lang/Object;")                        \
+    oop_field(CiTargetMethod_Call, debugInfo, "Lcom/sun/cri/ci/CiDebugInfo;")           \
+  end_class                                                                             \
+  start_class(CiTargetMethod_DataPatch)                                                 \
+    oop_field(CiTargetMethod_DataPatch, constant, "Lcom/sun/cri/ci/CiConstant;")        \
+  end_class                                                                             \
+  start_class(CiTargetMethod_Safepoint)                                                 \
+    oop_field(CiTargetMethod_Safepoint, debugInfo, "Lcom/sun/cri/ci/CiDebugInfo;")      \
+  end_class                                                                             \
+  start_class(CiTargetMethod_ExceptionHandler)                                          \
+    int_field(CiTargetMethod_ExceptionHandler, handlerPos)                              \
+    int_field(CiTargetMethod_ExceptionHandler, handlerBci)                              \
+    int_field(CiTargetMethod_ExceptionHandler, bci)                                     \
+    int_field(CiTargetMethod_ExceptionHandler, scopeLevel)                              \
+    oop_field(CiTargetMethod_ExceptionHandler, exceptionType, "Lcom/sun/cri/ri/RiType;")\
+  end_class                                                                             \
+  start_class(CiTargetMethod_Mark)                                                      \
+    oop_field(CiTargetMethod_Mark, id, "Ljava/lang/Object;")                            \
+    oop_field(CiTargetMethod_Mark, references, "[Lcom/sun/cri/ci/CiTargetMethod$Mark;") \
+  end_class                                                                             \
+  start_class(CiDebugInfo)                                                              \
+    oop_field(CiDebugInfo, codePos, "Lcom/sun/cri/ci/CiCodePos;")                       \
+    oop_field(CiDebugInfo, registerRefMap, "Lcom/oracle/max/graal/graph/BitMap;")       \
+    oop_field(CiDebugInfo, frameRefMap, "Lcom/oracle/max/graal/graph/BitMap;")          \
+  end_class                                                                             \
+  start_class(GraalBitMap)                                                              \
+    int_field(GraalBitMap, size)                                                        \
+    long_field(GraalBitMap, low)                                                        \
+    oop_field(GraalBitMap, extra, "[J")                                                 \
+  end_class                                                                             \
+  start_class(CiFrame)                                                                  \
+    oop_field(CiFrame, values, "[Lcom/sun/cri/ci/CiValue;")                             \
+    int_field(CiFrame, numLocals)                                                       \
+    int_field(CiFrame, numStack)                                                        \
+    int_field(CiFrame, numLocks)                                                        \
+    boolean_field(CiFrame, rethrowException)                                            \
+  end_class                                                                             \
+  start_class(CiCodePos)                                                                \
+    oop_field(CiCodePos, caller, "Lcom/sun/cri/ci/CiCodePos;")                          \
+    oop_field(CiCodePos, method, "Lcom/sun/cri/ri/RiMethod;")                           \
+    int_field(CiCodePos, bci)                                                           \
+  end_class                                                                             \
+  start_class(CiConstant)                                                               \
+    oop_field(CiConstant, kind, "Lcom/sun/cri/ci/CiKind;")                              \
+    oop_field(CiConstant, object, "Ljava/lang/Object;")                                 \
+    long_field(CiConstant, primitive)                                                   \
+  end_class                                                                             \
+  start_class(CiKind)                                                                   \
+    char_field(CiKind, typeChar)                                                        \
+    static_oop_field(CiKind, Boolean, "Lcom/sun/cri/ci/CiKind;");                       \
+    static_oop_field(CiKind, Byte, "Lcom/sun/cri/ci/CiKind;");                          \
+    static_oop_field(CiKind, Char, "Lcom/sun/cri/ci/CiKind;");                          \
+    static_oop_field(CiKind, Short, "Lcom/sun/cri/ci/CiKind;");                         \
+    static_oop_field(CiKind, Int, "Lcom/sun/cri/ci/CiKind;");                           \
+    static_oop_field(CiKind, Long, "Lcom/sun/cri/ci/CiKind;");                          \
+  end_class                                                                             \
+  start_class(CiRuntimeCall)                                                            \
+    static_oop_field(CiRuntimeCall, UnwindException, "Lcom/sun/cri/ci/CiRuntimeCall;"); \
+    static_oop_field(CiRuntimeCall, RegisterFinalizer, "Lcom/sun/cri/ci/CiRuntimeCall;"); \
+    static_oop_field(CiRuntimeCall, HandleException, "Lcom/sun/cri/ci/CiRuntimeCall;"); \
+    static_oop_field(CiRuntimeCall, OSRMigrationEnd, "Lcom/sun/cri/ci/CiRuntimeCall;"); \
+    static_oop_field(CiRuntimeCall, JavaTimeMillis, "Lcom/sun/cri/ci/CiRuntimeCall;");  \
+    static_oop_field(CiRuntimeCall, JavaTimeNanos, "Lcom/sun/cri/ci/CiRuntimeCall;");   \
+    static_oop_field(CiRuntimeCall, Debug, "Lcom/sun/cri/ci/CiRuntimeCall;");           \
+    static_oop_field(CiRuntimeCall, ArithmethicLrem, "Lcom/sun/cri/ci/CiRuntimeCall;"); \
+    static_oop_field(CiRuntimeCall, ArithmeticLdiv, "Lcom/sun/cri/ci/CiRuntimeCall;");  \
+    static_oop_field(CiRuntimeCall, ArithmeticFrem, "Lcom/sun/cri/ci/CiRuntimeCall;");  \
+    static_oop_field(CiRuntimeCall, ArithmeticDrem, "Lcom/sun/cri/ci/CiRuntimeCall;");  \
+    static_oop_field(CiRuntimeCall, ArithmeticCos, "Lcom/sun/cri/ci/CiRuntimeCall;");   \
+    static_oop_field(CiRuntimeCall, ArithmeticTan, "Lcom/sun/cri/ci/CiRuntimeCall;");   \
+    static_oop_field(CiRuntimeCall, ArithmeticLog, "Lcom/sun/cri/ci/CiRuntimeCall;");   \
+    static_oop_field(CiRuntimeCall, ArithmeticLog10, "Lcom/sun/cri/ci/CiRuntimeCall;"); \
+    static_oop_field(CiRuntimeCall, ArithmeticSin, "Lcom/sun/cri/ci/CiRuntimeCall;");   \
+    static_oop_field(CiRuntimeCall, Deoptimize, "Lcom/sun/cri/ci/CiRuntimeCall;");      \
+  end_class                                                                             \
+  start_class(RiMethod)                                                                 \
+  end_class                                                                             \
+  start_class(CiValue)                                                                  \
+    oop_field(CiValue, kind, "Lcom/sun/cri/ci/CiKind;")                                 \
+    static_oop_field(CiValue, IllegalValue, "Lcom/sun/cri/ci/CiValue;");                \
+  end_class                                                                             \
+  start_class(CiRegisterValue)                                                          \
+    oop_field(CiRegisterValue, reg, "Lcom/sun/cri/ci/CiRegister;")                      \
+  end_class                                                                             \
+  start_class(CiRegister)                                                               \
+    int_field(CiRegister, number)                                                       \
+  end_class                                                                             \
+  start_class(CiStackSlot)                                                              \
+    int_field(CiStackSlot, index)                                                       \
+  end_class                                                                             \
+  start_class(CiVirtualObject)                                                          \
+    int_field(CiVirtualObject, id)                                                      \
+    oop_field(CiVirtualObject, type, "Lcom/sun/cri/ri/RiType;")                         \
+    oop_field(CiVirtualObject, values, "[Lcom/sun/cri/ci/CiValue;")                     \
+  end_class                                                                             \
+  start_class(RiTypeProfile)                                                            \
+    int_field(RiTypeProfile, count)                                                     \
+    int_field(RiTypeProfile, morphism)                                                  \
+    oop_field(RiTypeProfile, probabilities, "[F")                                       \
+    oop_field(RiTypeProfile, types, "[Lcom/sun/cri/ri/RiType;")                         \
+  end_class                                                                             \
+  /* end*/
+
+#define START_CLASS(name)                       \
+class name : AllStatic {                      \
+  private:                                      \
+    friend class GraalCompiler;                   \
+    static void check(oop obj) { assert(obj != NULL, "NULL field access of class " #name); assert(obj->is_a(SystemDictionary::name##_klass()), "wrong class, " #name " expected"); } \
+    static void compute_offsets();              \
+  public:                                       \
+    static klassOop klass() { return SystemDictionary::name##_klass(); }
+
+#define END_CLASS };
+
+#define FIELD(name, type, accessor)             \
+    static int _##name##_offset;                \
+    static type name(oop obj)                   { check(obj); return obj->accessor(_##name##_offset); } \
+    static type name(Handle obj)                { check(obj()); return obj->accessor(_##name##_offset); } \
+    static type name(jobject obj)               { check(JNIHandles::resolve(obj)); return JNIHandles::resolve(obj)->accessor(_##name##_offset); } \
+    static void set_##name(oop obj, type x)     { check(obj); obj->accessor##_put(_##name##_offset, x); } \
+    static void set_##name(Handle obj, type x)  { check(obj()); obj->accessor##_put(_##name##_offset, x); } \
+    static void set_##name(jobject obj, type x) { check(JNIHandles::resolve(obj)); JNIHandles::resolve(obj)->accessor##_put(_##name##_offset, x); }
+
+#define CHAR_FIELD(klass, name) FIELD(name, jchar, char_field)
+#define INT_FIELD(klass, name) FIELD(name, jint, int_field)
+#define BOOLEAN_FIELD(klass, name) FIELD(name, jboolean, bool_field)
+#define LONG_FIELD(klass, name) FIELD(name, jlong, long_field)
+#define FLOAT_FIELD(klass, name) FIELD(name, jfloat, float_field)
+#define OOP_FIELD(klass, name, signature) FIELD(name, oop, obj_field)
+#define STATIC_OOP_FIELD(klassName, name, signature)                \
+    static int _##name##_offset;                                    \
+    static oop name() {                                             \
+      instanceKlass* ik = instanceKlass::cast(klassName::klass());  \
+      address addr = ik->static_field_addr(_##name##_offset - instanceMirrorKlass::offset_of_static_fields());       \
+      if (UseCompressedOops) {                                      \
+        return oopDesc::load_decode_heap_oop((narrowOop *)addr);    \
+      } else {                                                      \
+        return oopDesc::load_decode_heap_oop((oop*)addr);           \
+      }                                                             \
+    }                                                               \
+    static void set_##name(oop x) {                                 \
+      instanceKlass* ik = instanceKlass::cast(klassName::klass());  \
+      address addr = ik->static_field_addr(_##name##_offset - instanceMirrorKlass::offset_of_static_fields());       \
+      if (UseCompressedOops) {                                      \
+        oopDesc::encode_store_heap_oop((narrowOop *)addr, x);       \
+      } else {                                                      \
+        oopDesc::encode_store_heap_oop((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)
+#undef START_CLASS
+#undef END_CLASS
+#undef FIELD
+#undef CHAR_FIELD
+#undef INT_FIELD
+#undef BOOLEAN_FIELD
+#undef LONG_FIELD
+#undef FLOAT_FIELD
+#undef OOP_FIELD
+#undef STATIC_OOP_FIELD
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/graal/graalVMEntries.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,929 @@
+/*
+ * 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.
+ */
+
+#include "precompiled.hpp"
+#include "graal/graalVMEntries.hpp"
+#include "graal/graalCompiler.hpp"
+#include "graal/graalJavaAccess.hpp"
+#include "graal/graalCodeInstaller.hpp"
+#include "graal/graalVMExits.hpp"
+#include "graal/graalVmIds.hpp"
+#include "c1/c1_Runtime1.hpp"
+#include "memory/oopFactory.hpp"
+#include "ci/ciMethodData.hpp"
+
+methodOop getMethodFromHotSpotMethod(jobject hotspot_method) {
+  return getMethodFromHotSpotMethod(JNIHandles::resolve(hotspot_method));
+}
+
+methodOop getMethodFromHotSpotMethod(oop hotspot_method) {
+  oop reflected = HotSpotMethodResolved::javaMirror(hotspot_method);
+  assert(reflected != NULL, "NULL not expected");
+  return (methodOop)reflected;
+
+  // (tw) Cannot use reflection code, because then the compiler can dead lock with the user application (test using -Xcomp).
+  /*
+  // method is a handle to a java.lang.reflect.Method object
+  oop mirror     = NULL;
+  int slot       = 0;
+
+  if (reflected->klass() == SystemDictionary::reflect_Constructor_klass()) {
+    mirror = java_lang_reflect_Constructor::clazz(reflected);
+    slot   = java_lang_reflect_Constructor::slot(reflected);
+  } else {
+    assert(reflected->klass() == SystemDictionary::reflect_Method_klass(), "wrong type");
+    mirror = java_lang_reflect_Method::clazz(reflected);
+    slot   = java_lang_reflect_Method::slot(reflected);
+  }
+  klassOop k     = java_lang_Class::as_klassOop(mirror);
+
+  // Make sure class is initialized before handing id's out to methods
+//  assert(instanceKlass::cast(k)->is_initialized(), "only initialized classes expected");
+  methodOop m = instanceKlass::cast(k)->method_with_idnum(slot);
+  assert(m != NULL, "deleted method?");
+  return m;*/
+}
+
+oop getReflectedMethod(methodOop method, TRAPS) {
+  assert(method != NULL, "NULL not expected");
+
+  if (!method->is_initializer() || method->is_static()) {
+    return Reflection::new_method(method, true, true, CHECK_NULL);
+  } else {
+    return Reflection::new_constructor(method, CHECK_NULL);
+  }
+}
+
+// public byte[] RiMethod_code(long vmId);
+JNIEXPORT jbyteArray JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_1code(JNIEnv *env, jobject, jobject hotspot_method) {
+  TRACE_graal_3("VMEntries::RiMethod_code");
+  methodHandle method = getMethodFromHotSpotMethod(hotspot_method);
+  int code_size = method->code_size();
+  jbyteArray result = env->NewByteArray(code_size);
+  env->SetByteArrayRegion(result, 0, code_size, (const jbyte *) method->code_base());
+  return result;
+}
+
+// public String RiMethod_signature(long vmId);
+JNIEXPORT jstring JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_1signature(JNIEnv *env, jobject, jobject hotspot_method) {
+  TRACE_graal_3("VMEntries::RiMethod_signature");
+  VM_ENTRY_MARK
+  methodOop method = getMethodFromHotSpotMethod(hotspot_method);
+  assert(method != NULL && method->signature() != NULL, "signature required");
+  return VmIds::toString<jstring>(method->signature(), THREAD);
+}
+
+// public RiExceptionHandler[] RiMethod_exceptionHandlers(long vmId);
+JNIEXPORT jobjectArray JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_1exceptionHandlers(JNIEnv *, jobject, jobject hotspot_method) {
+  TRACE_graal_3("VMEntries::RiMethod_exceptionHandlers");
+  VM_ENTRY_MARK
+  methodHandle method = getMethodFromHotSpotMethod(hotspot_method);
+  typeArrayHandle handlers = method->exception_table();
+  int handler_count = handlers.is_null() ? 0 : handlers->length() / 4;
+
+  instanceKlass::cast(HotSpotExceptionHandler::klass())->initialize(CHECK_NULL);
+  objArrayHandle array = oopFactory::new_objArray(SystemDictionary::RiExceptionHandler_klass(), handler_count, CHECK_NULL);
+
+  for (int i = 0; i < handler_count; i++) {
+    // exception handlers are stored as four integers: start bci, end bci, handler bci, catch class constant pool index
+    int base = i * 4;
+    Handle entry = instanceKlass::cast(HotSpotExceptionHandler::klass())->allocate_instance(CHECK_NULL);
+    HotSpotExceptionHandler::set_startBci(entry, handlers->int_at(base + 0));
+    HotSpotExceptionHandler::set_endBci(entry, handlers->int_at(base + 1));
+    HotSpotExceptionHandler::set_handlerBci(entry, handlers->int_at(base + 2));
+    int catch_class_index = handlers->int_at(base + 3);
+    HotSpotExceptionHandler::set_catchClassIndex(entry, catch_class_index);
+
+    if (catch_class_index == 0) {
+      HotSpotExceptionHandler::set_catchClass(entry, NULL);
+    } else {
+      constantPoolOop cp = instanceKlass::cast(method->method_holder())->constants();
+      ciInstanceKlass* loading_klass = (ciInstanceKlass *) CURRENT_ENV->get_object(method->method_holder());
+      bool is_accessible = false;
+      ciKlass *klass = CURRENT_ENV->get_klass_by_index(cp, catch_class_index, is_accessible, loading_klass);
+      oop catch_class = GraalCompiler::get_RiType(klass, method->method_holder(), CHECK_NULL);
+
+      HotSpotExceptionHandler::set_catchClass(entry, catch_class);
+    }
+    array->obj_at_put(i, entry());
+  }
+
+  return (jobjectArray) JNIHandles::make_local(array());
+}
+
+// public boolean RiMethod_hasBalancedMonitors(long vmId);
+JNIEXPORT jint JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_1hasBalancedMonitors(JNIEnv *, jobject, jobject hotspot_method) {
+  TRACE_graal_3("VMEntries::RiMethod_hasBalancedMonitors");
+  ciMethod* cimethod;
+  {
+    VM_ENTRY_MARK;
+    methodOop method = getMethodFromHotSpotMethod(hotspot_method);
+    cimethod = (ciMethod*)CURRENT_ENV->get_object(method);
+  }
+  return cimethod->has_balanced_monitors();
+}
+
+// public boolean RiMethod_uniqueConcreteMethod(long vmId);
+JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_1uniqueConcreteMethod(JNIEnv *, jobject, jobject hotspot_method) {
+  TRACE_graal_3("VMEntries::RiMethod_uniqueConcreteMethod");
+  VM_ENTRY_MARK;
+  methodOop m = getMethodFromHotSpotMethod(hotspot_method);
+  ciMethod* cimethod = (ciMethod*)CURRENT_ENV->get_object(m);
+  if (cimethod->holder()->is_interface()) {
+    // Cannot trust interfaces. Because of:
+    // interface I { void foo(); }
+    // class A { public void foo() {} }
+    // class B extends A implements I { }
+    // class C extends B { public void foo() { } }
+    // class D extends B { }
+    // Would lead to identify C.foo() as the unique concrete method for I.foo() without seeing A.foo().
+    return false;
+  }
+  klassOop klass = (klassOop)cimethod->holder()->get_oop();
+  methodHandle method((methodOop)cimethod->get_oop());
+  methodHandle unique_concrete;
+  {
+    ResourceMark rm;
+    MutexLocker locker(Compile_lock);
+    unique_concrete = methodHandle(Dependencies::find_unique_concrete_method(klass, method()));
+  }
+  if (unique_concrete.is_null()) {
+    return NULL;
+  }
+
+  Handle name = VmIds::toString<Handle>(unique_concrete->name(), CHECK_NULL);
+  oop method_resolved = GraalCompiler::createHotSpotMethodResolved(unique_concrete(), name, CHECK_NULL);
+  return JNIHandles::make_local(THREAD, method_resolved);
+}
+
+// public native int RiMethod_invocationCount(long vmId);
+JNIEXPORT jint JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_1invocationCount(JNIEnv *, jobject, jobject hotspot_method) {
+  TRACE_graal_3("VMEntries::RiMethod_invocationCount");
+  methodOop method = getMethodFromHotSpotMethod(hotspot_method);
+  return method->invocation_count();
+}
+
+// public native int RiMethod_throwoutCount(long vmId);
+JNIEXPORT jint JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_2exceptionProbability(JNIEnv *, jobject, jobject hotspot_method, jint bci) {
+  TRACE_graal_3("VMEntries::RiMethod_exceptionProbability");
+  ciMethod* cimethod;
+  {
+    VM_ENTRY_MARK;
+    methodOop method = getMethodFromHotSpotMethod(hotspot_method);
+    cimethod = (ciMethod*)CURRENT_ENV->get_object(method);
+  }
+
+  ciMethodData* method_data = cimethod->method_data_or_null();
+  if (method_data == NULL) {
+    return -1;
+  } else {
+    ciProfileData* profile = method_data->bci_to_data(bci);
+    if (profile == NULL) {
+      return 0;
+    }
+    uint trap = method_data->trap_recompiled_at(profile);
+    if (trap > 0) {
+      return 100;
+    } else {
+      return trap;
+    }
+  }
+}
+
+// public native RiTypeProfile RiMethod_typeProfile(long vmId, int bci);
+JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_2typeProfile(JNIEnv *, jobject, jobject hotspot_method, jint bci) {
+  TRACE_graal_3("VMEntries::RiMethod_typeProfile");
+  ciMethod* cimethod;
+  {
+    VM_ENTRY_MARK;
+    methodOop method = getMethodFromHotSpotMethod(hotspot_method);
+    cimethod = (ciMethod*)CURRENT_ENV->get_object(method);
+  }
+
+  ciCallProfile profile = cimethod->call_profile_at_bci(bci);
+
+  Handle obj;
+  {
+    VM_ENTRY_MARK;
+    instanceKlass::cast(RiTypeProfile::klass())->initialize(CHECK_NULL);
+    obj = instanceKlass::cast(RiTypeProfile::klass())->allocate_instance(CHECK_NULL);
+    assert(obj() != NULL, "must succeed in allocating instance");
+
+    RiTypeProfile::set_count(obj, cimethod->scale_count(profile.count(), 1));
+    RiTypeProfile::set_morphism(obj, profile.morphism());
+
+    typeArrayHandle probabilities = oopFactory::new_typeArray(T_FLOAT, profile.limit(), CHECK_NULL);
+    objArrayHandle types = oopFactory::new_objArray(SystemDictionary::RiType_klass(), profile.limit(), CHECK_NULL);
+    for (int i=0; i<profile.limit(); i++) {
+      float prob = profile.receiver_prob(i);
+      ciKlass* receiver = profile.receiver(i);
+      oop type = GraalCompiler::get_RiType(receiver, KlassHandle(), CHECK_NULL);
+
+      probabilities->float_at_put(i, prob);
+      types->obj_at_put(i, type);
+    }
+
+    RiTypeProfile::set_probabilities(obj, probabilities());
+    RiTypeProfile::set_types(obj, types());
+
+  }
+
+  return JNIHandles::make_local(obj());
+}
+
+JNIEXPORT jdouble JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_2branchProbability(JNIEnv *, jobject, jobject hotspot_method, jint bci) {
+  TRACE_graal_3("VMEntries::RiMethod_typeProfile");
+  ciMethodData* method_data;
+  ciMethod* cimethod;
+  {
+    VM_ENTRY_MARK;
+    methodOop method = getMethodFromHotSpotMethod(hotspot_method);
+    cimethod = (ciMethod*)CURRENT_ENV->get_object(method);
+  }
+  method_data = cimethod->method_data();
+
+  jfloat probability = -1;
+
+  if (method_data == NULL || !method_data->is_mature()) return -1;
+
+  ciProfileData* data = method_data->bci_to_data(bci);
+  if (data == NULL || !data->is_JumpData())  return -1;
+
+  // get taken and not taken values
+  int     taken = data->as_JumpData()->taken();
+  int not_taken = 0;
+  if (data->is_BranchData()) {
+    not_taken = data->as_BranchData()->not_taken();
+  }
+
+  // Give up if too few (or too many, in which case the sum will overflow) counts to be meaningful.
+  // We also check that individual counters are positive first, otherwise the sum can become positive.
+  if (taken < 0 || not_taken < 0 || taken + not_taken < 40) return -1;
+
+  // Pin probability to sane limits
+  if (taken == 0)
+    return 0;
+  else if (not_taken == 0)
+    return 1;
+  else {                         // Compute probability of true path
+    return (jdouble)(taken) / (taken + not_taken);
+  }
+}
+
+JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_2switchProbability(JNIEnv *, jobject, jobject hotspot_method, jint bci) {
+  TRACE_graal_3("VMEntries::RiMethod_typeProfile");
+  ciMethodData* method_data;
+  ciMethod* cimethod;
+  {
+    VM_ENTRY_MARK;
+    methodOop method = getMethodFromHotSpotMethod(hotspot_method);
+    cimethod = (ciMethod*)CURRENT_ENV->get_object(method);
+  }
+  method_data = cimethod->method_data();
+
+  jfloat probability = -1;
+
+  if (method_data == NULL || !method_data->is_mature()) return NULL;
+
+  ciProfileData* data = method_data->bci_to_data(bci);
+  if (data == NULL || !data->is_MultiBranchData())  return NULL;
+
+  MultiBranchData* branch_data = data->as_MultiBranchData();
+
+  long sum = 0;
+  int cases = branch_data->number_of_cases();
+  GrowableArray<uint>* counts = new GrowableArray<uint>(cases + 1);
+
+  for (int i = 0; i < cases; i++) {
+    uint value = branch_data->count_at(i);
+    sum += value;
+    counts->append(value);
+  }
+  uint value = branch_data->default_count();
+  sum += value;
+  counts->append(value);
+
+  // Give up if too few (or too many, in which case the sum will overflow) counts to be meaningful.
+  // We also check that individual counters are positive first, otherwise the sum can become positive.
+  if (sum < 10 * (cases + 3)) return NULL;
+
+  {
+    VM_ENTRY_MARK;
+    typeArrayOop probability = oopFactory::new_typeArray(T_DOUBLE, cases + 1, CHECK_NULL);
+    for (int i = 0; i < cases + 1; i++) {
+      probability->double_at_put(i, counts->at(i) / (double) sum);
+    }
+    return JNIHandles::make_local(probability);
+  }
+}
+
+// public RiType RiSignature_lookupType(String returnType, HotSpotTypeResolved accessingClass);
+JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiSignature_1lookupType(JNIEnv *env, jobject, jstring jname, jobject accessingClass) {
+  TRACE_graal_3("VMEntries::RiSignature_lookupType");
+  VM_ENTRY_MARK;
+
+  Symbol* nameSymbol = VmIds::toSymbol(jname);
+  Handle name = JNIHandles::resolve(jname);
+
+  oop result;
+  if (nameSymbol == vmSymbols::int_signature()) {
+    result = VMExits::createRiTypePrimitive((int) T_INT, THREAD);
+  } else if (nameSymbol == vmSymbols::long_signature()) {
+    result = VMExits::createRiTypePrimitive((int) T_LONG, THREAD);
+  } else if (nameSymbol == vmSymbols::bool_signature()) {
+    result = VMExits::createRiTypePrimitive((int) T_BOOLEAN, THREAD);
+  } else if (nameSymbol == vmSymbols::char_signature()) {
+    result = VMExits::createRiTypePrimitive((int) T_CHAR, THREAD);
+  } else if (nameSymbol == vmSymbols::short_signature()) {
+    result = VMExits::createRiTypePrimitive((int) T_SHORT, THREAD);
+  } else if (nameSymbol == vmSymbols::byte_signature()) {
+    result = VMExits::createRiTypePrimitive((int) T_BYTE, THREAD);
+  } else if (nameSymbol == vmSymbols::double_signature()) {
+    result = VMExits::createRiTypePrimitive((int) T_DOUBLE, THREAD);
+  } else if (nameSymbol == vmSymbols::float_signature()) {
+    result = VMExits::createRiTypePrimitive((int) T_FLOAT, THREAD);
+  } else {
+    klassOop resolved_type = NULL;
+    // if the name isn't in the symbol table then the class isn't loaded anyway...
+    if (nameSymbol != NULL) {
+      Handle classloader;
+      Handle protectionDomain;
+      if (JNIHandles::resolve(accessingClass) != NULL) {
+        classloader = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(accessingClass))->klass_part()->class_loader();
+        protectionDomain = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(accessingClass))->klass_part()->protection_domain();
+      }
+      resolved_type = SystemDictionary::resolve_or_null(nameSymbol, classloader, protectionDomain, THREAD);
+      if (HAS_PENDING_EXCEPTION) {
+        CLEAR_PENDING_EXCEPTION;
+        resolved_type = NULL;
+      }
+    }
+    if (resolved_type != NULL) {
+      result = GraalCompiler::createHotSpotTypeResolved(resolved_type, name, CHECK_NULL);
+    } else {
+      result = VMExits::createRiTypeUnresolved(name, THREAD);
+    }
+  }
+
+  return JNIHandles::make_local(THREAD, result);
+}
+
+// public Object RiConstantPool_lookupConstant(long vmId, int cpi);
+JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupConstant(JNIEnv *env, jobject, jlong vmId, jint index) {
+  TRACE_graal_3("VMEntries::RiConstantPool_lookupConstant");
+  VM_ENTRY_MARK;
+
+  constantPoolOop cp = VmIds::get<constantPoolOop>(vmId);
+
+  oop result = NULL;
+  constantTag tag = cp->tag_at(index);
+  if (tag.is_int()) {
+    result = VMExits::createCiConstant(CiKind::Int(), cp->int_at(index), CHECK_0);
+  } else if (tag.is_long()) {
+    result = VMExits::createCiConstant(CiKind::Long(), cp->long_at(index), CHECK_0);
+  } else if (tag.is_float()) {
+    result = VMExits::createCiConstantFloat(cp->float_at(index), CHECK_0);
+  } else if (tag.is_double()) {
+    result = VMExits::createCiConstantDouble(cp->double_at(index), CHECK_0);
+  } else if (tag.is_string() || tag.is_unresolved_string()) {
+    oop string = NULL;
+    if (cp->is_pseudo_string_at(index)) {
+      string = cp->pseudo_string_at(index);
+    } else {
+      string = cp->string_at(index, THREAD);
+      if (HAS_PENDING_EXCEPTION) {
+        CLEAR_PENDING_EXCEPTION;
+        // TODO: Gracefully exit compilation.
+        fatal("out of memory during compilation!");
+        return NULL;
+      }
+    }
+    result = VMExits::createCiConstantObject(string, CHECK_0);
+  } else if (tag.is_klass() || tag.is_unresolved_klass()) {
+    bool ignore;
+    ciInstanceKlass* accessor = (ciInstanceKlass*) ciEnv::current()->get_object(cp->pool_holder());
+    ciKlass* klass = ciEnv::current()->get_klass_by_index(cp, index, ignore, accessor);
+    result = GraalCompiler::get_RiType(klass, cp->pool_holder(), CHECK_NULL);
+  } else if (tag.is_object()) {
+    oop obj = cp->object_at(index);
+    assert(obj->is_instance(), "must be an instance");
+    result = VMExits::createCiConstantObject(obj, CHECK_NULL);
+  } else {
+    ShouldNotReachHere();
+  }
+
+  return JNIHandles::make_local(THREAD, result);
+}
+
+// public RiMethod RiConstantPool_lookupMethod(long vmId, int cpi, byte byteCode);
+JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupMethod(JNIEnv *env, jobject, jlong vmId, jint index, jbyte byteCode) {
+  TRACE_graal_3("VMEntries::RiConstantPool_lookupMethod");
+  VM_ENTRY_MARK;
+  index = GraalCompiler::to_cp_index_u2(index);
+  constantPoolHandle cp = VmIds::get<constantPoolOop>(vmId);
+
+  Bytecodes::Code bc = (Bytecodes::Code) (((int) byteCode) & 0xFF);
+  ciInstanceKlass* loading_klass = (ciInstanceKlass *) CURRENT_ENV->get_object(cp->pool_holder());
+  ciMethod *cimethod = CURRENT_ENV->get_method_by_index(cp, index, bc, loading_klass);
+  if (cimethod->is_loaded()) {
+    methodOop method = (methodOop) cimethod->get_oop();
+    Handle name = VmIds::toString<Handle>(method->name(), CHECK_NULL);
+    oop ret = GraalCompiler::createHotSpotMethodResolved(method, name, CHECK_NULL);
+    return JNIHandles::make_local(THREAD, ret);
+  } else {
+    Handle name = VmIds::toString<Handle>(cimethod->name()->get_symbol(), CHECK_NULL);
+    Handle signature = VmIds::toString<Handle>(cimethod->signature()->as_symbol()->get_symbol(), CHECK_NULL);
+    Handle holder = GraalCompiler::get_RiType(cimethod->holder(), cp->klass(), THREAD);
+    return JNIHandles::make_local(THREAD, VMExits::createRiMethodUnresolved(name, signature, holder, THREAD));
+  }
+}
+
+// public RiSignature RiConstantPool_lookupSignature(long vmId, int cpi);
+JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupSignature(JNIEnv *env, jobject, jlong vmId, jint index) {
+  fatal("currently unsupported");
+  return NULL;
+}
+
+// public RiType RiConstantPool_lookupType(long vmId, int cpi);
+JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupType(JNIEnv *env, jobject, jlong vmId, jint index) {
+  TRACE_graal_3("VMEntries::RiConstantPool_lookupType");
+  VM_ENTRY_MARK;
+
+  constantPoolOop cp = VmIds::get<constantPoolOop>(vmId);
+
+  ciInstanceKlass* loading_klass = (ciInstanceKlass *) CURRENT_ENV->get_object(cp->pool_holder());
+  bool is_accessible = false;
+  ciKlass *klass = CURRENT_ENV->get_klass_by_index(cp, index, is_accessible, loading_klass);
+  return JNIHandles::make_local(THREAD, GraalCompiler::get_RiType(klass, cp->klass(), THREAD));
+}
+
+// public RiField RiConstantPool_lookupField(long vmId, int cpi);
+JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupField(JNIEnv *env, jobject, jlong vmId, jint index, jbyte byteCode) {
+  TRACE_graal_3("VMEntries::RiConstantPool_lookupField");
+  VM_ENTRY_MARK;
+
+  index = GraalCompiler::to_cp_index_u2(index);
+  constantPoolOop cp = VmIds::get<constantPoolOop>(vmId);
+
+  ciInstanceKlass* loading_klass = (ciInstanceKlass *) CURRENT_ENV->get_object(cp->pool_holder());
+  ciField *field = CURRENT_ENV->get_field_by_index(loading_klass, index);
+  
+  Bytecodes::Code code = (Bytecodes::Code)(((int) byteCode) & 0xFF);
+  Handle field_handle = GraalCompiler::get_RiField(field, loading_klass, cp->pool_holder(), code, THREAD);
+  bool is_constant = field->is_constant();
+  if (is_constant && field->is_static()) {
+    ciConstant constant = field->constant_value();
+    oop constant_object = NULL;
+    switch (constant.basic_type()) {
+      case T_OBJECT:
+      case T_ARRAY:
+        {
+          ciObject* obj = constant.as_object();
+          if (obj->is_null_object()) {
+            constant_object = VMExits::createCiConstantObject(NULL, CHECK_0);
+          } else if (obj->can_be_constant()) {
+            constant_object = VMExits::createCiConstantObject(constant.as_object()->get_oop(), CHECK_0);
+          }
+        }
+        break;
+      case T_DOUBLE:
+        constant_object = VMExits::createCiConstantDouble(constant.as_double(), CHECK_0);
+        break;
+      case T_FLOAT:
+        constant_object = VMExits::createCiConstantFloat(constant.as_float(), CHECK_0);
+        break;
+      case T_LONG:
+        constant_object = VMExits::createCiConstant(CiKind::Long(), constant.as_long(), CHECK_0);
+        break;
+      case T_INT:
+        constant_object = VMExits::createCiConstant(CiKind::Int(), constant.as_int(), CHECK_0);
+        break;
+      case T_SHORT:
+        constant_object = VMExits::createCiConstant(CiKind::Short(), constant.as_int(), CHECK_0);
+        break;
+      case T_CHAR:
+        constant_object = VMExits::createCiConstant(CiKind::Char(), constant.as_int(), CHECK_0);
+        break;
+      case T_BYTE:
+        constant_object = VMExits::createCiConstant(CiKind::Byte(), constant.as_int(), CHECK_0);
+        break;
+      case T_BOOLEAN:
+        constant_object = VMExits::createCiConstant(CiKind::Boolean(), constant.as_int(), CHECK_0);
+        break;
+      default:
+        constant.print();
+        fatal("Unhandled constant");
+        break;
+    }
+    if (constant_object != NULL) {
+      HotSpotField::set_constant(field_handle, constant_object);
+    }
+  }
+  return JNIHandles::make_local(THREAD, field_handle());
+}
+
+// public RiConstantPool RiType_constantPool(HotSpotTypeResolved klass);
+JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiType_1constantPool(JNIEnv *, jobject, jobject klass) {
+  TRACE_graal_3("VMEntries::RiType_constantPool");
+  VM_ENTRY_MARK;
+
+  assert(JNIHandles::resolve(klass) != NULL, "");
+  constantPoolOop constantPool = ((instanceKlass*)java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass))->klass_part())->constants();
+  return JNIHandles::make_local(VMExits::createRiConstantPool(VmIds::add<constantPoolOop>(constantPool), THREAD));
+}
+
+// public RiMethod RiType_resolveMethodImpl(HotSpotTypeResolved klass, String name, String signature);
+JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiType_3resolveMethodImpl(JNIEnv *, jobject, jobject resolved_type, jstring name, jstring signature) {
+  TRACE_graal_3("VMEntries::RiType_resolveMethodImpl");
+  VM_ENTRY_MARK;
+
+  assert(JNIHandles::resolve(resolved_type) != NULL, "");
+  klassOop klass = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(resolved_type));
+  Symbol* name_symbol = VmIds::toSymbol(name);
+  Symbol* signature_symbol = VmIds::toSymbol(signature);
+  methodOop method = klass->klass_part()->lookup_method(name_symbol, signature_symbol);
+  if (method == NULL) {
+    if (TraceGraal >= 3) {
+      ResourceMark rm;
+      tty->print_cr("Could not resolve method %s %s on klass %s", name_symbol->as_C_string(), signature_symbol->as_C_string(), klass->klass_part()->name()->as_C_string());
+    }
+    return NULL;
+  }
+  oop ret = GraalCompiler::createHotSpotMethodResolved(method, Handle(JNIHandles::resolve(name)), CHECK_NULL);
+  return JNIHandles::make_local(THREAD, ret);
+}
+
+// public boolean RiType_isSubtypeOf(HotSpotTypeResolved klass, RiType other);
+JNIEXPORT jboolean JNICALL Java_com_oracle_graal_runtime_VMEntries_RiType_2isSubtypeOf(JNIEnv *, jobject, jobject klass, jobject jother) {
+  TRACE_graal_3("VMEntries::RiType_isSubtypeOf");
+  oop other = JNIHandles::resolve(jother);
+  assert(other->is_a(HotSpotTypeResolved::klass()), "resolved hotspot type expected");
+  assert(JNIHandles::resolve(klass) != NULL, "");
+  klassOop thisKlass = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass));
+  klassOop otherKlass = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(other));
+  if (thisKlass->klass_part()->oop_is_instance_slow()) {
+    return instanceKlass::cast(thisKlass)->is_subtype_of(otherKlass);
+  } else if (thisKlass->klass_part()->oop_is_array()) {
+    return arrayKlass::cast(thisKlass)->is_subtype_of(otherKlass);
+  } else {
+    fatal("unexpected class type");
+    return false;
+  }
+}
+
+// public RiType RiType_componentType(HotSpotResolvedType klass);
+JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiType_1componentType(JNIEnv *, jobject, jobject klass) {
+  TRACE_graal_3("VMEntries::RiType_componentType");
+  ciArrayKlass* array_klass;
+  {
+    VM_ENTRY_MARK;
+    assert(JNIHandles::resolve(klass) != NULL, "");
+    array_klass = (ciArrayKlass *) CURRENT_ENV->get_object(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass)));
+  }
+  ciType* element_type = array_klass->element_type();
+
+  VM_ENTRY_MARK;
+  assert(JNIHandles::resolve(klass) != NULL, "");
+  return JNIHandles::make_local(GraalCompiler::get_RiType(element_type, java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass)), THREAD));
+}
+
+// public RiType RiType_superType(HotSpotResolvedType klass);
+JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiType_1superType(JNIEnv *, jobject, jobject klass) {
+  TRACE_graal_3("VMEntries::RiType_superType");
+  VM_ENTRY_MARK;
+  KlassHandle klass_handle(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass)));
+  ciInstanceKlass* k = NULL;
+
+  if (klass_handle->oop_is_array()) {
+    k = (ciInstanceKlass *) CURRENT_ENV->get_object(SystemDictionary::Object_klass());
+  } else {
+    guarantee(klass_handle->oop_is_instance(), "must be instance klass");  
+    k = (ciInstanceKlass *) CURRENT_ENV->get_object(klass_handle());
+    k = k->super();
+  }
+
+  if (k != NULL) {
+    return JNIHandles::make_local(GraalCompiler::get_RiType(k, klass_handle, THREAD));
+  } else {
+    return NULL;
+  }
+}
+
+// public RiType RiType_uniqueConcreteSubtype(HotSpotResolvedType klass);
+JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiType_1uniqueConcreteSubtype(JNIEnv *, jobject, jobject klass) {
+  TRACE_graal_3("VMEntries::RiType_uniqueConcreteSubtype");
+  Thread* THREAD = Thread::current();
+  KlassHandle klass_handle(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass)));
+  ciInstanceKlass* k = NULL;
+  {
+    VM_ENTRY_MARK;
+    k = (ciInstanceKlass *) CURRENT_ENV->get_object(klass_handle());
+  }
+
+  if (k->is_abstract()) {
+    ciInstanceKlass* sub = k->unique_concrete_subklass();
+    if (sub != NULL && sub->is_leaf_type()) {
+      VM_ENTRY_MARK;
+      return JNIHandles::make_local(GraalCompiler::get_RiType(sub, klass_handle, THREAD));
+    }
+  } else if (k->is_leaf_type()) {
+    assert(!k->is_interface(), "");
+    return klass;
+  }
+
+  return NULL;
+}
+
+// public bool RiType_isInitialized(HotSpotResolvedType klass);
+JNIEXPORT jboolean JNICALL Java_com_oracle_graal_runtime_VMEntries_RiType_1isInitialized(JNIEnv *, jobject, jobject hotspot_klass) {
+  TRACE_graal_3("VMEntries::RiType_isInitialized");
+  klassOop klass = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(hotspot_klass));
+  return instanceKlass::cast(klass)->is_initialized();
+}
+
+// public RiType RiType_arrayOf(HotSpotTypeResolved klass);
+JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiType_1arrayOf(JNIEnv *, jobject, jobject klass) {
+  TRACE_graal_3("VMEntries::RiType_arrayOf");
+  VM_ENTRY_MARK;
+
+  KlassHandle klass_handle(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass)));
+  KlassHandle array = klass_handle->array_klass(THREAD);
+  Handle name = VmIds::toString<Handle>(array->name(), CHECK_NULL);
+  return JNIHandles::make_local(THREAD, GraalCompiler::createHotSpotTypeResolved(array, name, THREAD));
+}
+
+// public RiField[] RiType_fields(HotSpotTypeResolved klass);
+JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiType_1fields(JNIEnv *, jobject, jobject klass) {
+  TRACE_graal_3("VMEntries::RiType_fields");
+  KlassHandle klass_handle;
+  ciInstanceKlass* instance_klass;
+  objArrayHandle fieldsArray;
+  HandleMark hm;
+  {
+    VM_ENTRY_MARK;
+    klass_handle = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass));
+    instance_klass = (ciInstanceKlass *) CURRENT_ENV->get_object(klass_handle());
+  }
+  GrowableArray<ciField*>* fields = instance_klass->non_static_fields();
+  {
+    VM_ENTRY_MARK;
+    fieldsArray = oopFactory::new_objArray(SystemDictionary::RiField_klass(), fields->length(), CHECK_NULL);
+    for (int i = 0; i < fields->length(); i++) {
+      ciField* field = fields->at(i);
+      Handle field_handle = GraalCompiler::get_RiField(field, instance_klass, klass_handle, Bytecodes::_illegal, CHECK_NULL);
+      fieldsArray->obj_at_put(i, field_handle());
+    }
+  }
+  return JNIHandles::make_local(fieldsArray());
+}
+
+// public RiType getPrimitiveArrayType(CiKind kind);
+JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_getPrimitiveArrayType(JNIEnv *env, jobject, jobject kind) {
+  TRACE_graal_3("VMEntries::VMEntries_getPrimitiveArrayType");
+  VM_ENTRY_MARK;
+  BasicType type = GraalCompiler::kindToBasicType(CiKind::typeChar(kind));
+  assert(type != T_OBJECT, "primitive type expecteds");
+  ciKlass* klass = ciTypeArrayKlass::make(type);
+  return JNIHandles::make_local(THREAD, GraalCompiler::get_RiType(klass, KlassHandle(), THREAD));
+}
+
+// public RiType getType(Class<?> javaClass);
+JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_getType(JNIEnv *env, jobject, jobject javaClass) {
+  TRACE_graal_3("VMEntries::VMEntries_getType");
+  VM_ENTRY_MARK;
+  oop javaClassOop = JNIHandles::resolve(javaClass);
+  if (javaClassOop == NULL) {
+    fatal("argument to VMEntries.getType must not be NULL");
+    return NULL;
+  } else if (java_lang_Class::is_primitive(javaClassOop)) {
+    BasicType basicType = java_lang_Class::primitive_type(javaClassOop);
+    return JNIHandles::make_local(THREAD, VMExits::createRiTypePrimitive((int) basicType, THREAD));
+  } else {
+    KlassHandle klass = java_lang_Class::as_klassOop(javaClassOop);
+    Handle name = java_lang_String::create_from_symbol(klass->name(), CHECK_NULL);
+
+    oop type = GraalCompiler::createHotSpotTypeResolved(klass, name, CHECK_NULL);
+    return JNIHandles::make_local(THREAD, type);
+  }
+}
+
+
+// helpers used to set fields in the HotSpotVMConfig object
+jfieldID getFieldID(JNIEnv* env, jobject obj, const char* name, const char* sig) {
+  jfieldID id = env->GetFieldID(env->GetObjectClass(obj), name, sig);
+  if (id == NULL) {
+    TRACE_graal_1("field not found: %s (%s)", name, sig);
+    fatal("field not found");
+  }
+  return id;
+}
+
+void set_boolean(JNIEnv* env, jobject obj, const char* name, bool value) { env->SetBooleanField(obj, getFieldID(env, obj, name, "Z"), value); }
+void set_int(JNIEnv* env, jobject obj, const char* name, int value) { env->SetIntField(obj, getFieldID(env, obj, name, "I"), value); }
+void set_long(JNIEnv* env, jobject obj, const char* name, jlong value) { env->SetLongField(obj, getFieldID(env, obj, name, "J"), value); }
+void set_object(JNIEnv* env, jobject obj, const char* name, jobject value) { env->SetObjectField(obj, getFieldID(env, obj, name, "Ljava/lang/Object;"), value); }
+void set_int_array(JNIEnv* env, jobject obj, const char* name, jarray value) { env->SetObjectField(obj, getFieldID(env, obj, name, "[I"), value); }
+
+jboolean get_boolean(JNIEnv* env, jobject obj, const char* name) { return env->GetBooleanField(obj, getFieldID(env, obj, name, "Z")); }
+jint get_int(JNIEnv* env, jobject obj, const char* name) { return env->GetIntField(obj, getFieldID(env, obj, name, "I")); }
+jlong get_long(JNIEnv* env, jobject obj, const char* name) { return env->GetLongField(obj, getFieldID(env, obj, name, "J")); }
+jobject get_object(JNIEnv* env, jobject obj, const char* name) { return env->GetObjectField(obj, getFieldID(env, obj, name, "Ljava/lang/Object;")); }
+jobject get_object(JNIEnv* env, jobject obj, const char* name, const char* sig) { return env->GetObjectField(obj, getFieldID(env, obj, name, sig)); }
+
+
+BasicType basicTypes[] = { T_BOOLEAN, T_BYTE, T_SHORT, T_CHAR, T_INT, T_FLOAT, T_LONG, T_DOUBLE, T_OBJECT };
+int basicTypeCount = sizeof(basicTypes) / sizeof(BasicType);
+
+// public HotSpotVMConfig getConfiguration();
+JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_getConfiguration(JNIEnv *env, jobject) {
+  jclass klass = env->FindClass("com/oracle/max/graal/runtime/HotSpotVMConfig");
+  assert(klass != NULL, "HotSpot vm config class not found");
+  jobject config = env->AllocObject(klass);
+#ifdef _WIN64
+  set_boolean(env, config, "windowsOs", true);
+#else
+  set_boolean(env, config, "windowsOs", false);
+#endif
+  set_boolean(env, config, "verifyPointers", VerifyOops);
+  set_boolean(env, config, "useFastLocking", UseFastLocking);
+  set_boolean(env, config, "useFastNewObjectArray", UseFastNewObjectArray);
+  set_boolean(env, config, "useFastNewTypeArray", UseFastNewTypeArray);
+  set_int(env, config, "codeEntryAlignment", CodeEntryAlignment);
+  set_int(env, config, "vmPageSize", os::vm_page_size());
+  set_int(env, config, "stackShadowPages", StackShadowPages);
+  set_int(env, config, "hubOffset", oopDesc::klass_offset_in_bytes());
+  set_int(env, config, "arrayLengthOffset", arrayOopDesc::length_offset_in_bytes());
+  set_int(env, config, "klassStateOffset", instanceKlass::init_state_offset_in_bytes() + sizeof(oopDesc));
+  set_int(env, config, "klassStateFullyInitialized", (int)instanceKlass::fully_initialized);
+  set_int(env, config, "threadTlabTopOffset", in_bytes(JavaThread::tlab_top_offset()));
+  set_int(env, config, "threadTlabEndOffset", in_bytes(JavaThread::tlab_end_offset()));
+  set_int(env, config, "threadObjectOffset", in_bytes(JavaThread::threadObj_offset()));
+  set_int(env, config, "instanceHeaderPrototypeOffset", Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes());
+  set_int(env, config, "threadExceptionOopOffset", in_bytes(JavaThread::exception_oop_offset()));
+  set_int(env, config, "threadExceptionPcOffset", in_bytes(JavaThread::exception_pc_offset()));
+  set_int(env, config, "threadMultiNewArrayStorage", in_bytes(JavaThread::graal_multinewarray_storage_offset()));
+  set_int(env, config, "classMirrorOffset", klassOopDesc::klass_part_offset_in_bytes() + Klass::java_mirror_offset_in_bytes());
+
+  set_long(env, config, "debugStub", VmIds::addStub((address)warning));
+  set_long(env, config, "instanceofStub", VmIds::addStub(Runtime1::entry_for(Runtime1::slow_subtype_check_id)));
+  set_long(env, config, "verifyPointerStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_verify_pointer_id)));
+  set_long(env, config, "newInstanceStub", VmIds::addStub(Runtime1::entry_for(Runtime1::fast_new_instance_init_check_id)));
+  set_long(env, config, "unresolvedNewInstanceStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_instance_id)));
+  set_long(env, config, "newTypeArrayStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_type_array_id)));
+  set_long(env, config, "newObjectArrayStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_object_array_id)));
+  set_long(env, config, "newMultiArrayStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_multi_array_id)));
+  set_long(env, config, "loadKlassStub", VmIds::addStub(Runtime1::entry_for(Runtime1::load_klass_patching_id)));
+  set_long(env, config, "accessFieldStub", VmIds::addStub(Runtime1::entry_for(Runtime1::access_field_patching_id)));
+  set_long(env, config, "resolveStaticCallStub", VmIds::addStub(SharedRuntime::get_resolve_static_call_stub()));
+  set_long(env, config, "inlineCacheMissStub", VmIds::addStub(SharedRuntime::get_ic_miss_stub()));
+  set_long(env, config, "unwindExceptionStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_unwind_exception_call_id)));
+  set_long(env, config, "handleExceptionStub", VmIds::addStub(Runtime1::entry_for(Runtime1::handle_exception_nofpu_id)));
+  set_long(env, config, "handleDeoptStub", VmIds::addStub(SharedRuntime::deopt_blob()->unpack()));
+  set_long(env, config, "monitorEnterStub", VmIds::addStub(Runtime1::entry_for(Runtime1::monitorenter_id)));
+  set_long(env, config, "monitorExitStub", VmIds::addStub(Runtime1::entry_for(Runtime1::monitorexit_id)));
+  set_long(env, config, "fastMonitorEnterStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_monitorenter_id)));
+  set_long(env, config, "fastMonitorExitStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_monitorexit_id)));
+  set_long(env, config, "safepointPollingAddress", (jlong)(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size())));
+
+  BarrierSet* bs = Universe::heap()->barrier_set();
+  switch (bs->kind()) {
+    case BarrierSet::CardTableModRef:
+    case BarrierSet::CardTableExtension: {
+      jlong base = (jlong)((CardTableModRefBS*)bs)->byte_map_base;
+      assert(base != 0, "unexpected byte_map_base");
+      set_long(env, config, "cardtableStartAddress", base);
+      set_int(env, config, "cardtableShift", CardTableModRefBS::card_shift);
+      break;
+    }
+    case BarrierSet::ModRef:
+    case BarrierSet::Other:
+      set_long(env, config, "cardtableStartAddress", 0);
+      set_int(env, config, "cardtableShift", 0);
+      // No post barriers
+      break;
+#ifndef SERIALGC
+    case BarrierSet::G1SATBCT:
+    case BarrierSet::G1SATBCTLogging:
+#endif // SERIALGC
+    default:
+      ShouldNotReachHere();
+      break;
+    }
+
+  jintArray arrayOffsets = env->NewIntArray(basicTypeCount);
+  for (int i=0; i<basicTypeCount; i++) {
+    jint offset = arrayOopDesc::base_offset_in_bytes(basicTypes[i]);
+    env->SetIntArrayRegion(arrayOffsets, i, 1, &offset);
+  }
+  set_int_array(env, config, "arrayOffsets", arrayOffsets);
+  set_int(env, config, "arrayClassElementOffset", objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc));
+  return config;
+}
+
+// public void installMethod(HotSpotTargetMethod targetMethod);
+JNIEXPORT void JNICALL Java_com_oracle_graal_runtime_VMEntries_installMethod(JNIEnv *jniEnv, jobject, jobject targetMethod) {
+  VM_ENTRY_MARK;
+  CodeInstaller installer(JNIHandles::resolve(targetMethod));
+}
+
+// public HotSpotProxy installStub(HotSpotTargetMethod targetMethod, String name);
+JNIEXPORT jlong JNICALL Java_com_oracle_graal_runtime_VMEntries_installStub(JNIEnv *jniEnv, jobject, jobject targetMethod) {
+  VM_ENTRY_MARK;
+  jlong id;
+  CodeInstaller installer(JNIHandles::resolve(targetMethod), id);
+  return id;
+}
+
+// public void recordBailout(String reason);
+JNIEXPORT void JNICALL Java_com_oracle_graal_runtime_VMEntries_recordBailout(JNIEnv *jniEnv, jobject, jobject message) {
+  if (GraalBailoutIsFatal) {
+    Handle msg = JNIHandles::resolve(message);
+    if (!msg.is_null()) {
+      java_lang_String::print(msg, tty);
+    }
+    vm_abort(false);
+  }
+}
+
+
+
+
+#define CC (char*)  /*cast a literal from (const char*)*/
+#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
+
+#define PROXY           "J"
+#define TYPE            "Lcom/sun/cri/ri/RiType;"
+#define RESOLVED_TYPE   "Lcom/oracle/max/graal/runtime/HotSpotTypeResolved;"
+#define METHOD          "Lcom/sun/cri/ri/RiMethod;"
+#define RESOLVED_METHOD "Lcom/oracle/max/graal/runtime/HotSpotMethodResolved;"
+#define TYPE_PROFILE    "Lcom/sun/cri/ri/RiTypeProfile;"
+#define SIGNATURE       "Lcom/sun/cri/ri/RiSignature;"
+#define FIELD           "Lcom/sun/cri/ri/RiField;"
+#define CONSTANT_POOL   "Lcom/sun/cri/ri/RiConstantPool;"
+#define EXCEPTION_HANDLERS "[Lcom/sun/cri/ri/RiExceptionHandler;"
+#define TARGET_METHOD   "Lcom/oracle/max/graal/runtime/HotSpotTargetMethod;"
+#define CONFIG          "Lcom/oracle/max/graal/runtime/HotSpotVMConfig;"
+#define HS_METHOD       "Lcom/oracle/max/graal/runtime/HotSpotMethod;"
+#define CI_CONSTANT     "Lcom/sun/cri/ci/CiConstant;"
+#define CI_KIND         "Lcom/sun/cri/ci/CiKind;"
+#define STRING          "Ljava/lang/String;"
+#define OBJECT          "Ljava/lang/Object;"
+#define CLASS           "Ljava/lang/Class;"
+
+JNINativeMethod VMEntries_methods[] = {
+  {CC"RiMethod_code",                   CC"("RESOLVED_METHOD")[B",                  FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1code)},
+  {CC"RiMethod_signature",              CC"("RESOLVED_METHOD")"STRING,              FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1signature)},
+  {CC"RiMethod_exceptionHandlers",      CC"("RESOLVED_METHOD")"EXCEPTION_HANDLERS,  FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1exceptionHandlers)},
+  {CC"RiMethod_hasBalancedMonitors",    CC"("RESOLVED_METHOD")Z",                   FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1hasBalancedMonitors)},
+  {CC"RiMethod_uniqueConcreteMethod",   CC"("RESOLVED_METHOD")"METHOD,              FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1uniqueConcreteMethod)},
+  {CC"RiMethod_typeProfile",            CC"("RESOLVED_METHOD"I)"TYPE_PROFILE,       FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_2typeProfile)},
+  {CC"RiMethod_branchProbability",      CC"("RESOLVED_METHOD"I)D",                  FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_2branchProbability)},
+  {CC"RiMethod_switchProbability",      CC"("RESOLVED_METHOD"I)[D",                 FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_2switchProbability)},
+  {CC"RiMethod_invocationCount",        CC"("RESOLVED_METHOD")I",                   FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1invocationCount)},
+  {CC"RiMethod_exceptionProbability",   CC"("RESOLVED_METHOD"I)I",                  FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_2exceptionProbability)},
+  {CC"RiSignature_lookupType",          CC"("STRING RESOLVED_TYPE")"TYPE,           FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiSignature_1lookupType)},
+  {CC"RiConstantPool_lookupConstant",   CC"("PROXY"I)"OBJECT,                       FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupConstant)},
+  {CC"RiConstantPool_lookupMethod",     CC"("PROXY"IB)"METHOD,                      FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupMethod)},
+  {CC"RiConstantPool_lookupSignature",  CC"("PROXY"I)"SIGNATURE,                    FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupSignature)},
+  {CC"RiConstantPool_lookupType",       CC"("PROXY"I)"TYPE,                         FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupType)},
+  {CC"RiConstantPool_lookupField",      CC"("PROXY"IB)"FIELD,                       FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupField)},
+  {CC"RiType_constantPool",             CC"("RESOLVED_TYPE")"CONSTANT_POOL,         FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiType_1constantPool)},
+  {CC"RiType_resolveMethodImpl",        CC"("RESOLVED_TYPE STRING STRING")"METHOD,  FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiType_3resolveMethodImpl)},
+  {CC"RiType_isSubtypeOf",              CC"("RESOLVED_TYPE TYPE")Z",                FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiType_2isSubtypeOf)},
+  {CC"RiType_componentType",            CC"("RESOLVED_TYPE")"TYPE,                  FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiType_1componentType)},
+  {CC"RiType_uniqueConcreteSubtype",    CC"("RESOLVED_TYPE")"TYPE,                  FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiType_1uniqueConcreteSubtype)},
+  {CC"RiType_superType",                CC"("RESOLVED_TYPE")"TYPE,                  FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiType_1superType)},
+  {CC"RiType_arrayOf",                  CC"("RESOLVED_TYPE")"TYPE,                  FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiType_1arrayOf)},
+  {CC"RiType_fields",                   CC"("RESOLVED_TYPE")["FIELD,                FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiType_1fields)},
+  {CC"RiType_isInitialized",            CC"("RESOLVED_TYPE")Z",                     FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiType_1isInitialized)},
+  {CC"getPrimitiveArrayType",           CC"("CI_KIND")"TYPE,                        FN_PTR(Java_com_oracle_graal_runtime_VMEntries_getPrimitiveArrayType)},
+  {CC"getType",                         CC"("CLASS")"TYPE,                          FN_PTR(Java_com_oracle_graal_runtime_VMEntries_getType)},
+  {CC"getConfiguration",                CC"()"CONFIG,                               FN_PTR(Java_com_oracle_graal_runtime_VMEntries_getConfiguration)},
+  {CC"installMethod",                   CC"("TARGET_METHOD")V",                     FN_PTR(Java_com_oracle_graal_runtime_VMEntries_installMethod)},
+  {CC"installStub",                     CC"("TARGET_METHOD")"PROXY,                 FN_PTR(Java_com_oracle_graal_runtime_VMEntries_installStub)},
+  {CC"recordBailout",                   CC"("STRING")V",                            FN_PTR(Java_com_oracle_graal_runtime_VMEntries_recordBailout)}
+};
+
+int VMEntries_methods_count() {
+  return sizeof(VMEntries_methods) / sizeof(JNINativeMethod);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/graal/graalVMEntries.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+#include "prims/jni.h"
+
+extern JNINativeMethod VMEntries_methods[];
+int VMEntries_methods_count();
+
+methodOop getMethodFromHotSpotMethod(oop hotspotMethod);
+
+oop getReflectedMethod(methodOop method, TRAPS);
+
+// nothing here - no need to define the jni method implementations in a header file
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/graal/graalVMExits.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,288 @@
+/*
+ * 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.
+ */
+
+#include "precompiled.hpp"
+#include "graal/graalVMExits.hpp"
+
+// this is a *global* handle
+jobject VMExits::_compilerPermObject = NULL;
+jobject VMExits::_vmExitsPermObject = NULL;
+jobject VMExits::_vmExitsPermKlass = NULL;
+
+KlassHandle VMExits::vmExitsKlass() {
+  if (JNIHandles::resolve(_vmExitsPermKlass) == NULL) {
+    klassOop result = SystemDictionary::resolve_or_null(vmSymbols::com_sun_hotspot_graal_VMExits(), SystemDictionary::java_system_loader(), NULL, Thread::current());
+    check_not_null(result, "Couldn't find class com.sun.hotspot.graal.VMExits");
+    _vmExitsPermKlass = JNIHandles::make_global(result);
+  }
+  return KlassHandle((klassOop)JNIHandles::resolve_non_null(_vmExitsPermKlass));
+}
+
+Handle VMExits::compilerInstance() {
+  if (JNIHandles::resolve(_compilerPermObject) == NULL) {
+    KlassHandle compilerImplKlass = SystemDictionary::resolve_or_null(vmSymbols::com_sun_hotspot_graal_CompilerImpl(), SystemDictionary::java_system_loader(), NULL, Thread::current());
+    check_not_null(compilerImplKlass(), "Couldn't find class com.sun.hotspot.graal.CompilerImpl");
+
+    JavaValue result(T_OBJECT);
+    JavaCalls::call_static(&result, compilerImplKlass, vmSymbols::getInstance_name(), vmSymbols::getInstance_signature(), Thread::current());
+    check_pending_exception("Couldn't get Compiler");
+    _compilerPermObject = JNIHandles::make_global((oop) result.get_jobject());
+  }
+  return Handle(JNIHandles::resolve_non_null(_compilerPermObject));
+}
+
+Handle VMExits::instance() {
+  if (JNIHandles::resolve(_vmExitsPermObject) == NULL) {
+    KlassHandle compilerKlass = SystemDictionary::resolve_or_null(vmSymbols::com_sun_hotspot_graal_Compiler(), SystemDictionary::java_system_loader(), NULL, Thread::current());
+    check_not_null(compilerKlass(), "Couldn't find class com.sun.hotspot.graal.Compiler");
+
+    JavaValue result(T_OBJECT);
+    JavaCallArguments args;
+    args.set_receiver(compilerInstance());
+    JavaCalls::call_interface(&result, compilerKlass, vmSymbols::getVMExits_name(), vmSymbols::getVMExits_signature(), &args, Thread::current());
+    check_pending_exception("Couldn't get VMExits");
+    _vmExitsPermObject = JNIHandles::make_global((oop) result.get_jobject());
+  }
+  return Handle(JNIHandles::resolve_non_null(_vmExitsPermObject));
+}
+
+void VMExits::initializeCompiler() {
+  KlassHandle compilerImplKlass = SystemDictionary::resolve_or_null(vmSymbols::com_sun_hotspot_graal_CompilerImpl(), SystemDictionary::java_system_loader(), NULL, Thread::current());
+  check_not_null(compilerImplKlass(), "Couldn't find class com.sun.hotspot.graal.CompilerImpl");
+
+  JavaValue result(T_VOID);
+  JavaCalls::call_static(&result, compilerImplKlass, vmSymbols::initialize_name(), vmSymbols::void_method_signature(), Thread::current());
+  check_pending_exception("Couldn't initialize compiler");
+
+  startCompiler();
+}
+
+jboolean VMExits::setOption(Handle option) {
+  assert(!option.is_null(), "");
+  KlassHandle compilerKlass = SystemDictionary::resolve_or_null(vmSymbols::com_sun_hotspot_graal_HotSpotOptions(), SystemDictionary::java_system_loader(), NULL, Thread::current());
+  check_not_null(compilerKlass(), "Couldn't find class com.sun.hotspot.graal.HotSpotOptions");
+
+  Thread* THREAD = Thread::current();
+  JavaValue result(T_BOOLEAN);
+  JavaCalls::call_static(&result, compilerKlass, vmSymbols::setOption_name(), vmSymbols::setOption_signature(), option, THREAD);
+  check_pending_exception("Error while calling setOption");
+  return result.get_jboolean();
+}
+
+void VMExits::setDefaultOptions() {
+  KlassHandle compilerKlass = SystemDictionary::resolve_or_null(vmSymbols::com_sun_hotspot_graal_HotSpotOptions(), SystemDictionary::java_system_loader(), NULL, Thread::current());
+  check_not_null(compilerKlass(), "Couldn't find class com.sun.hotspot.graal.HotSpotOptions");
+
+  Thread* THREAD = Thread::current();
+  JavaValue result(T_VOID);
+  JavaCalls::call_static(&result, compilerKlass, vmSymbols::setDefaultOptions_name(), vmSymbols::void_method_signature(), THREAD);
+  check_pending_exception("Error while calling setDefaultOptions");
+}
+
+void VMExits::compileMethod(Handle hotspot_method, int entry_bci) {
+  assert(!hotspot_method.is_null(), "just checking");
+  Thread* THREAD = Thread::current();
+  JavaValue result(T_VOID);
+  JavaCallArguments args;
+  args.push_oop(instance());
+  args.push_oop(hotspot_method);
+  args.push_int(entry_bci);
+  JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::compileMethod_name(), vmSymbols::compileMethod_signature(), &args, THREAD);
+  check_pending_exception("Error while calling compileMethod");
+}
+
+void VMExits::shutdownCompiler() {
+  if (_compilerPermObject != NULL) {
+    HandleMark hm;
+    JavaThread* THREAD = JavaThread::current();
+    JavaValue result(T_VOID);
+    JavaCallArguments args;
+    args.push_oop(instance());
+    JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::shutdownCompiler_name(), vmSymbols::void_method_signature(), &args, THREAD);
+    check_pending_exception("Error while calling shutdownCompiler");
+
+    JNIHandles::destroy_global(_compilerPermObject);
+    JNIHandles::destroy_global(_vmExitsPermObject);
+    JNIHandles::destroy_global(_vmExitsPermKlass);
+
+    _compilerPermObject = NULL;
+    _vmExitsPermObject = NULL;
+    _vmExitsPermKlass = NULL;
+  }
+}
+
+void VMExits::startCompiler() {
+  JavaThread* THREAD = JavaThread::current();
+  JavaValue result(T_VOID);
+  JavaCallArguments args;
+  args.push_oop(instance());
+  JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::startCompiler_name(), vmSymbols::void_method_signature(), &args, THREAD);
+  check_pending_exception("Error while calling startCompiler");
+}
+
+oop VMExits::createRiMethodResolved(jlong vmId, Handle name, TRAPS) {
+  assert(!name.is_null(), "just checking");
+  JavaValue result(T_OBJECT);
+  JavaCallArguments args;
+  args.push_oop(instance());
+  args.push_long(vmId);
+  args.push_oop(name);
+  JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiMethodResolved_name(), vmSymbols::createRiMethodResolved_signature(), &args, THREAD);
+  check_pending_exception("Error while calling createRiMethodResolved");
+  return (oop) result.get_jobject();
+}
+
+oop VMExits::createRiMethodUnresolved(Handle name, Handle signature, Handle holder, TRAPS) {
+  assert(!name.is_null(), "just checking");
+  JavaValue result(T_OBJECT);
+  JavaCallArguments args;
+  args.push_oop(instance());
+  args.push_oop(name);
+  args.push_oop(signature);
+  args.push_oop(holder);
+  JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiMethodUnresolved_name(), vmSymbols::createRiMethodUnresolved_signature(), &args, THREAD);
+  check_pending_exception("Error while calling createRiMethodUnresolved");
+  return (oop) result.get_jobject();
+}
+
+oop VMExits::createRiField(Handle holder, Handle name, Handle type, int index, int flags, TRAPS) {
+  assert(!holder.is_null(), "just checking");
+  assert(!name.is_null(), "just checking");
+  assert(!type.is_null(), "just checking");
+  JavaValue result(T_OBJECT);
+  JavaCallArguments args;
+  args.push_oop(instance());
+  args.push_oop(holder);
+  args.push_oop(name);
+  args.push_oop(type);
+  args.push_int(index);
+  args.push_int(flags);
+  JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiField_name(), vmSymbols::createRiField_signature(), &args, THREAD);
+  check_pending_exception("Error while calling createRiField");
+  assert(result.get_type() == T_OBJECT, "just checking");
+  return (oop) result.get_jobject();
+}
+
+oop VMExits::createRiType(jlong vmId, Handle name, TRAPS) {
+  assert(!name.is_null(), "just checking");
+  JavaValue result(T_OBJECT);
+  JavaCallArguments args;
+  args.push_oop(instance());
+  args.push_long(vmId);
+  args.push_oop(name);
+  JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiType_name(), vmSymbols::createRiType_signature(), &args, THREAD);
+  check_pending_exception("Error while calling createRiType");
+  return (oop) result.get_jobject();
+}
+
+oop VMExits::createRiTypePrimitive(int basic_type, TRAPS) {
+  JavaValue result(T_OBJECT);
+  JavaCallArguments args;
+  args.push_oop(instance());
+  args.push_int(basic_type);
+  JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiTypePrimitive_name(), vmSymbols::createRiTypePrimitive_signature(), &args, THREAD);
+  check_pending_exception("Error while calling createRiTypePrimitive");
+  return (oop) result.get_jobject();
+}
+
+oop VMExits::createRiTypeUnresolved(Handle name, TRAPS) {
+  assert(!name.is_null(), "just checking");
+  JavaValue result(T_OBJECT);
+  JavaCallArguments args;
+  args.push_oop(instance());
+  args.push_oop(name);
+  JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiTypeUnresolved_name(), vmSymbols::createRiTypeUnresolved_signature(), &args, THREAD);
+  check_pending_exception("Error while calling createRiTypeUnresolved");
+  return (oop) result.get_jobject();
+}
+
+oop VMExits::createRiConstantPool(jlong vmId, TRAPS) {
+  JavaValue result(T_OBJECT);
+  JavaCallArguments args;
+  args.push_oop(instance());
+  args.push_long(vmId);
+  JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiConstantPool_name(), vmSymbols::createRiConstantPool_signature(), &args, THREAD);
+  check_pending_exception("Error while calling createRiConstantPool");
+  return (oop) result.get_jobject();
+}
+
+oop VMExits::createRiSignature(Handle name, TRAPS) {
+  assert(!name.is_null(), "just checking");
+  JavaValue result(T_OBJECT);
+  JavaCallArguments args;
+  args.push_oop(instance());
+  args.push_oop(name);
+  JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiSignature_name(), vmSymbols::createRiSignature_signature(), &args, THREAD);
+  check_pending_exception("Error while calling createRiSignature");
+  return (oop) result.get_jobject();
+}
+
+oop VMExits::createCiConstant(Handle kind, jlong value, TRAPS) {
+  JavaValue result(T_OBJECT);
+  JavaCallArguments args;
+  args.push_oop(instance());
+  args.push_oop(kind());
+  args.push_long(value);
+  JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createCiConstant_name(), vmSymbols::createCiConstant_signature(), &args, THREAD);
+  check_pending_exception("Error while calling createCiConstantFloat");
+  return (oop) result.get_jobject();
+
+}
+
+oop VMExits::createCiConstantFloat(jfloat value, TRAPS) {
+  JavaValue result(T_OBJECT);
+  JavaCallArguments args;
+  args.push_oop(instance());
+  args.push_float(value);
+  JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createCiConstantFloat_name(), vmSymbols::createCiConstantFloat_signature(), &args, THREAD);
+  check_pending_exception("Error while calling createCiConstantFloat");
+  return (oop) result.get_jobject();
+
+}
+
+oop VMExits::createCiConstantDouble(jdouble value, TRAPS) {
+  JavaValue result(T_OBJECT);
+  JavaCallArguments args;
+  args.push_oop(instance());
+  args.push_double(value);
+  JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createCiConstantDouble_name(), vmSymbols::createCiConstantDouble_signature(), &args, THREAD);
+  check_pending_exception("Error while calling createCiConstantDouble");
+  return (oop) result.get_jobject();
+}
+
+oop VMExits::createCiConstantObject(Handle object, TRAPS) {
+  JavaValue result(T_OBJECT);
+  JavaCallArguments args;
+  /*
+  args.push_oop(instance());
+  args.push_oop(object);
+  JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createCiConstantObject_name(), vmSymbols::createCiConstantObject_signature(), &args, THREAD);
+  check_pending_exception("Error while calling createCiConstantObject");
+  */
+
+
+  KlassHandle klass = SystemDictionary::resolve_or_null(vmSymbols::com_sun_cri_ci_CiConstant(), SystemDictionary::java_system_loader(), NULL, Thread::current());
+  JavaCalls::call_static(&result, klass(), vmSymbols::forObject_name(), vmSymbols::createCiConstantObject_signature(), object, THREAD);
+  check_pending_exception("Error while calling CiConstant.forObject");
+  return (oop) result.get_jobject();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/graal/graalVMExits.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ */
+
+#include "memory/allocation.hpp"
+#include "oops/oop.hpp"
+#include "runtime/handles.hpp"
+#include "runtime/thread.hpp"
+#include "classfile/javaClasses.hpp"
+#include "runtime/jniHandles.hpp"
+#include "runtime/javaCalls.hpp"
+
+class VMExits : public AllStatic {
+
+private:
+  static jobject _compilerPermObject;
+  static jobject _vmExitsPermObject;
+  static jobject _vmExitsPermKlass;
+
+  static KlassHandle vmExitsKlass();
+  static Handle instance();
+
+public:
+  static void initializeCompiler();
+
+  static Handle compilerInstance();
+
+  // public static boolean HotSpotOptions.setOption(String option);
+  static jboolean setOption(Handle option);
+
+  // public static void HotSpotOptions.setDefaultOptions();
+  static void setDefaultOptions();
+
+  // public abstract void compileMethod(long vmId, String name, int entry_bci);
+  static void compileMethod(Handle hotspot_method, int entry_bci);
+
+  // public abstract void shutdownCompiler();
+  static void shutdownCompiler();
+  
+  // public abstract void startCompiler();
+  static void startCompiler();
+
+  // public abstract RiMethod createRiMethodResolved(long vmId, String name);
+  static oop createRiMethodResolved(jlong vmId, Handle name, TRAPS);
+
+  // public abstract RiMethod createRiMethodUnresolved(String name, String signature, RiType holder);
+  static oop createRiMethodUnresolved(Handle name, Handle signature, Handle holder, TRAPS);
+
+  // public abstract RiField createRiField(RiType holder, String name, RiType type, int flags, int offset);
+  static oop createRiField(Handle holder, Handle name, Handle type, int index, int flags, TRAPS);
+
+  // public abstract RiType createRiType(long vmId, String name);
+  static oop createRiType(jlong vmId, Handle name, TRAPS);
+
+  // public abstract RiType createRiTypeUnresolved(String name);
+  static oop createRiTypeUnresolved(Handle name, TRAPS);
+
+  // public abstract RiConstantPool createRiConstantPool(long vmId);
+  static oop createRiConstantPool(jlong vmId, TRAPS);
+
+  // public abstract RiType createRiTypePrimitive(int basicType);
+  static oop createRiTypePrimitive(int basicType, TRAPS);
+
+  // public abstract RiSignature createRiSignature(String signature);
+  static oop createRiSignature(Handle name, TRAPS);
+
+  // public abstract CiConstant createCiConstant(CiKind kind, long value);
+  static oop createCiConstant(Handle kind, jlong value, TRAPS);
+
+  // public abstract CiConstant createCiConstantFloat(float value);
+  static oop createCiConstantFloat(jfloat value, TRAPS);
+
+  // public abstract CiConstant createCiConstantDouble(double value);
+  static oop createCiConstantDouble(jdouble value, TRAPS);
+
+  // public abstract CiConstant createCiConstantObject(long vmId);
+  static oop createCiConstantObject(Handle object, TRAPS);
+};
+
+inline void check_pending_exception(const char* message, bool dump_core = false) {
+  Thread* THREAD = Thread::current();
+  if (THREAD->has_pending_exception()) {
+    Handle exception = PENDING_EXCEPTION;
+    CLEAR_PENDING_EXCEPTION;
+    tty->print_cr("%s", message);
+    java_lang_Throwable::print(exception, tty);
+    tty->cr();
+    java_lang_Throwable::print_stack_trace(exception(), tty);
+    vm_abort(dump_core);
+  }
+}
+
+inline void check_not_null(void* value, const char* message, bool dump_core = false) {
+  if (value == NULL) {
+    tty->print_cr("%s", message);
+    vm_abort(dump_core);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/graal/graalVmIds.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+#include "precompiled.hpp"
+#include "graal/graalVmIds.hpp"
+#include "ci/ciUtilities.hpp"
+
+// VmIds implementation
+
+GrowableArray<address>* VmIds::_stubs = NULL;
+GrowableArray<jobject>* VmIds::_localHandles = NULL;
+
+
+void VmIds::initializeObjects() {
+  if (_stubs == NULL) {
+    assert(_localHandles == NULL, "inconsistent state");
+    _stubs = new (ResourceObj::C_HEAP) GrowableArray<address> (64, true);
+    _localHandles = new (ResourceObj::C_HEAP) GrowableArray<jobject> (64, true);
+  }
+  assert(_localHandles->length() == 0, "invalid state");
+}
+
+void VmIds::cleanupLocalObjects() {
+  for (int i = 0; i < _localHandles->length(); i++) {
+    JNIHandles::destroy_global(_localHandles->at(i));
+  }
+  _localHandles->clear();
+}
+
+jlong VmIds::addStub(address stub) {
+  assert(!_stubs->contains(stub), "duplicate stub");
+  return _stubs->append(stub) | STUB;
+}
+
+jlong VmIds::add(Handle obj, jlong type) {
+  assert(!obj.is_null(), "cannot add NULL handle");
+  int idx = -1;
+  for (int i = 0; i < _localHandles->length(); i++)
+    if (JNIHandles::resolve_non_null(_localHandles->at(i)) == obj()) {
+      idx = i;
+      break;
+    }
+  if (idx == -1) {
+    if (JavaThread::current()->thread_state() == _thread_in_vm) {
+      idx = _localHandles->append(JNIHandles::make_global(obj));
+    } else {
+      VM_ENTRY_MARK;
+      idx = _localHandles->append(JNIHandles::make_global(obj));
+    }
+  }
+  return idx | type;
+}
+
+address VmIds::getStub(jlong id) {
+  assert((id & TYPE_MASK) == STUB, "wrong id type, STUB expected");
+  assert((id & ~TYPE_MASK) >= 0 && (id & ~TYPE_MASK) < _stubs->length(), "STUB index out of bounds");
+  return _stubs->at(id & ~TYPE_MASK);
+}
+
+oop VmIds::getObject(jlong id) {
+  assert((id & TYPE_MASK) != STUB, "wrong id type");
+  assert((id & ~TYPE_MASK) >= 0 && (id & ~TYPE_MASK) < _localHandles->length(), "index out of bounds");
+  return JNIHandles::resolve_non_null(_localHandles->at(id & ~TYPE_MASK));
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/graal/graalVmIds.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -0,0 +1,142 @@
+/*
+ * 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.
+ */
+
+#include "memory/allocation.hpp"
+#include "utilities/growableArray.hpp"
+#include "oops/oop.hpp"
+#include "runtime/handles.hpp"
+#include "runtime/thread.hpp"
+#include "classfile/javaClasses.hpp"
+#include "runtime/jniHandles.hpp"
+
+class VmIds : public AllStatic {
+
+private:
+  static GrowableArray<address>* _stubs;
+  static GrowableArray<jobject>* _localHandles;
+
+  static oop getObject(jlong id);
+
+public:
+  // these constants needs to have the same values as the one in HotSpotProxy.java
+  static const jlong STUB           = 0x100000000000000LL;        // address
+  static const jlong METHOD         = 0x200000000000000LL;        // methodOop
+  static const jlong CLASS          = 0x300000000000000LL;        // klassOop
+  static const jlong CONSTANT_POOL  = 0x500000000000000LL;        // constantPoolOop
+  static const jlong CONSTANT       = 0x600000000000000LL;        // oop
+  static const jlong TYPE_MASK      = 0xf00000000000000LL;
+  static const jlong DUMMY_CONSTANT = 0x6ffffffffffffffLL;
+
+  // Initializes the VmIds for a compilation, by creating the arrays
+  static void initializeObjects();
+  // Cleans up after a compilation, by deallocating the arrays
+  static void cleanupLocalObjects();
+
+  // Adds a stub address, and returns the corresponding vmId (which is of type STUB)
+  static jlong addStub(address stub);
+
+  // Adds an object, and returns the corresponding vmId (with the given type)
+  static jlong add(Handle obj, jlong type);
+
+  // Adds an object, and returns the corresponding vmId (the type of which is determined by the template parameter)
+  template <typename T> static jlong add(T obj);
+
+
+  // Returns the stub address with the given vmId
+  static address getStub(jlong id);
+  // Returns the stub address with the given vmId taken from a java.lang.Long
+  static address getStub(oop id);
+
+  // Returns the object with the given id, the return type is defined by the template parameter (which must correspond to the actual type of the vmId)
+  template <typename T> static T get(jlong id);
+
+
+  // Helper function to convert a symbol to a java.lang.String object
+  template <typename T> static T toString(Symbol* symbol, TRAPS);
+
+  // Helper function to convert a java.lang.String object to a symbol (this will return NULL if the symbol doesn't exist in the system)
+  static Symbol* toSymbol(jstring string);
+
+  // Helper function to get the contents of a java.lang.Long
+  static jlong getBoxedLong(oop obj);
+};
+
+
+template <> inline jlong VmIds::add<klassOop>(klassOop obj) {
+  assert(obj != NULL, "trying to add NULL<klassOop>");
+  assert(obj->is_klass(), "trying to add mistyped object");
+  return add(Handle(obj), CLASS);
+}
+template <> inline jlong VmIds::add<constantPoolOop>(constantPoolOop obj) {
+  assert(obj != NULL, "trying to add NULL<constantPoolOop>");
+  assert(obj->is_constantPool(), "trying to add mistyped object");
+  return add(Handle(obj), CONSTANT_POOL);
+}
+template <> inline jlong VmIds::add<oop>(oop obj) {
+  assert(obj != NULL, "trying to add NULL<oop>");
+  assert(obj->is_oop(), "trying to add mistyped object");
+  return add(Handle(obj), CONSTANT);
+}
+
+
+template <> inline klassOop VmIds::get<klassOop>(jlong id) {
+  assert((id & TYPE_MASK) == CLASS, "CLASS expected");
+  assert(getObject(id)->is_klass(), "klassOop expected");
+  return (klassOop)getObject(id);
+}
+template <> inline constantPoolOop VmIds::get<constantPoolOop>(jlong id) {
+  assert((id & TYPE_MASK) == CONSTANT_POOL, "CONSTANT_POOL expected");
+  assert(getObject(id)->is_constantPool(), "constantPoolOop expected");
+  return (constantPoolOop)getObject(id);
+}
+template <> inline oop VmIds::get<oop>(jlong id) {
+  assert((id & TYPE_MASK) == CONSTANT, "CONSTANT expected");
+  assert(getObject(id)->is_oop(true), "oop expected");
+  return (oop)getObject(id);
+}
+
+inline address VmIds::getStub(oop obj) {
+  return getStub(getBoxedLong(obj));
+}
+
+template <> inline Handle VmIds::toString<Handle>(Symbol* symbol, TRAPS) {
+  return java_lang_String::create_from_symbol(symbol, THREAD);
+}
+template <> inline oop VmIds::toString<oop>(Symbol* symbol, TRAPS) {
+  return toString<Handle>(symbol, THREAD)();
+}
+template <> inline jstring VmIds::toString<jstring>(Symbol* symbol, TRAPS) {
+  return (jstring)JNIHandles::make_local(toString<oop>(symbol, THREAD));
+}
+template <> inline jobject VmIds::toString<jobject>(Symbol* symbol, TRAPS) {
+  return JNIHandles::make_local(toString<oop>(symbol, THREAD));
+}
+
+inline Symbol* VmIds::toSymbol(jstring string) {
+  return java_lang_String::as_symbol_or_null(JNIHandles::resolve(string));
+}
+
+inline jlong VmIds::getBoxedLong(oop obj) {
+  assert(obj->is_oop(true), "cannot unbox null or non-oop");
+  return obj->long_field(java_lang_boxing_object::value_offset_in_bytes(T_LONG));
+}
--- a/src/share/vm/interpreter/interpreterRuntime.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/interpreter/interpreterRuntime.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -445,6 +445,18 @@
     }
   } while (should_repeat == true);
 
+  if (h_method->method_data() != NULL) {
+    ResourceMark rm(thread);
+    ProfileData* pdata = h_method->method_data()->allocate_bci_to_data(current_bci);
+    if (pdata != NULL) {
+      int tstate0 = pdata->trap_state();
+      int tstate1 = Deoptimization::trap_state_set_recompiled(tstate0, true);
+      if (tstate1 != tstate0) {
+        pdata->set_trap_state(tstate1);
+      }
+    }
+  }
+
   // notify JVMTI of an exception throw; JVMTI will detect if this is a first
   // time throw or a stack unwinding throw and accordingly notify the debugger
   if (JvmtiExport::can_post_on_exceptions()) {
--- a/src/share/vm/interpreter/rewriter.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/interpreter/rewriter.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -118,7 +118,7 @@
   while (!bcs.is_last_bytecode()) {
     Bytecodes::Code opcode = bcs.raw_next();
     switch (opcode) {
-      case Bytecodes::_return: *bcs.bcp() = Bytecodes::_return_register_finalizer; break;
+      case Bytecodes::_return: if (!UseGraal) { *bcs.bcp() = Bytecodes::_return_register_finalizer; } break;
 
       case Bytecodes::_istore:
       case Bytecodes::_lstore:
@@ -273,12 +273,14 @@
       switch (c) {
         case Bytecodes::_lookupswitch   : {
 #ifndef CC_INTERP
-          Bytecode_lookupswitch bc(method, bcp);
-          (*bcp) = (
-            bc.number_of_pairs() < BinarySwitchThreshold
-            ? Bytecodes::_fast_linearswitch
-            : Bytecodes::_fast_binaryswitch
-          );
+          if (!UseGraal) {
+            Bytecode_lookupswitch bc(method, bcp);
+            (*bcp) = (
+              bc.number_of_pairs() < BinarySwitchThreshold
+              ? Bytecodes::_fast_linearswitch
+              : Bytecodes::_fast_binaryswitch
+            );
+          }
 #endif
           break;
         }
--- a/src/share/vm/interpreter/templateTable.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/interpreter/templateTable.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -429,7 +429,8 @@
   def(Bytecodes::_jsr                 , ubcp|disp|____|____, vtos, vtos, jsr                 ,  _           ); // result is not an oop, so do not transition to atos
   def(Bytecodes::_ret                 , ubcp|disp|____|____, vtos, vtos, ret                 ,  _           );
   def(Bytecodes::_tableswitch         , ubcp|disp|____|____, itos, vtos, tableswitch         ,  _           );
-  def(Bytecodes::_lookupswitch        , ubcp|disp|____|____, itos, itos, lookupswitch        ,  _           );
+//  def(Bytecodes::_lookupswitch        , ubcp|disp|____|____, itos, itos, lookupswitch        ,  _           );
+  def(Bytecodes::_lookupswitch        , ubcp|disp|____|____, itos, vtos, fast_linearswitch   ,  _           );
   def(Bytecodes::_ireturn             , ____|disp|clvm|____, itos, itos, _return             , itos         );
   def(Bytecodes::_lreturn             , ____|disp|clvm|____, ltos, ltos, _return             , ltos         );
   def(Bytecodes::_freturn             , ____|disp|clvm|____, ftos, ftos, _return             , ftos         );
--- a/src/share/vm/oops/klass.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/oops/klass.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -148,6 +148,7 @@
   }
 
   kl->set_java_mirror(NULL);
+  kl->set_graal_mirror(NULL);
   kl->set_modifier_flags(0);
   kl->set_layout_helper(Klass::_lh_neutral_value);
   kl->set_name(NULL);
--- a/src/share/vm/oops/klass.hpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/oops/klass.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -237,6 +237,8 @@
   klassOop    _primary_supers[_primary_super_limit];
   // java/lang/Class instance mirroring this class
   oop       _java_mirror;
+  // com/oracle/max/graal/runtime/HotSpotTypeResolved mirroring this class
+  oop       _graal_mirror;
   // Superclass
   klassOop  _super;
   // First subclass (NULL if none); _subklass->next_sibling() is next one
@@ -334,6 +336,10 @@
   oop java_mirror() const              { return _java_mirror; }
   void set_java_mirror(oop m)          { oop_store((oop*) &_java_mirror, m); }
 
+  // graal mirror
+  oop graal_mirror() const               { return _graal_mirror; }
+  void set_graal_mirror(oop m)           { oop_store((oop*) &_graal_mirror, m); }
+
   // modifier flags
   jint modifier_flags() const          { return _modifier_flags; }
   void set_modifier_flags(jint flags)  { _modifier_flags = flags; }
@@ -362,6 +368,7 @@
   oop* adr_secondary_super_cache() const { return (oop*)&_secondary_super_cache; }
   oop* adr_secondary_supers()const { return (oop*)&_secondary_supers;  }
   oop* adr_java_mirror()     const { return (oop*)&_java_mirror;       }
+  oop* adr_graal_mirror()    const { return (oop*)&_graal_mirror;      }
   oop* adr_subklass()        const { return (oop*)&_subklass;          }
   oop* adr_next_sibling()    const { return (oop*)&_next_sibling;      }
 
--- a/src/share/vm/oops/klassKlass.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/oops/klassKlass.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -73,6 +73,7 @@
   MarkSweep::mark_and_push(k->adr_secondary_super_cache());
   MarkSweep::mark_and_push(k->adr_secondary_supers());
   MarkSweep::mark_and_push(k->adr_java_mirror());
+  MarkSweep::mark_and_push(k->adr_graal_mirror());
   // We follow the subklass and sibling links at the end of the
   // marking phase, since otherwise following them will prevent
   // class unloading (all classes are transitively linked from
@@ -92,6 +93,7 @@
   PSParallelCompact::mark_and_push(cm, k->adr_secondary_super_cache());
   PSParallelCompact::mark_and_push(cm, k->adr_secondary_supers());
   PSParallelCompact::mark_and_push(cm, k->adr_java_mirror());
+  PSParallelCompact::mark_and_push(cm, k->adr_graal_mirror());
   // We follow the subklass and sibling links at the end of the
   // marking phase, since otherwise following them will prevent
   // class unloading (all classes are transitively linked from
@@ -111,6 +113,7 @@
   blk->do_oop(k->adr_secondary_super_cache());
   blk->do_oop(k->adr_secondary_supers());
   blk->do_oop(k->adr_java_mirror());
+  blk->do_oop(k->adr_graal_mirror());
   // The following are in the perm gen and are treated
   // specially in a later phase of a perm gen collection; ...
   assert(oop(k)->is_perm(), "should be in perm");
@@ -144,6 +147,8 @@
   if (mr.contains(adr)) blk->do_oop(adr);
   adr = k->adr_java_mirror();
   if (mr.contains(adr)) blk->do_oop(adr);
+  adr = k->adr_graal_mirror();
+  if (mr.contains(adr)) blk->do_oop(adr);
   // The following are "weak links" in the perm gen and are
   // treated specially in a later phase of a perm gen collection.
   assert(oop(k)->is_perm(), "should be in perm");
@@ -172,6 +177,7 @@
   MarkSweep::adjust_pointer(k->adr_secondary_super_cache());
   MarkSweep::adjust_pointer(k->adr_secondary_supers());
   MarkSweep::adjust_pointer(k->adr_java_mirror());
+  MarkSweep::adjust_pointer(k->adr_graal_mirror());
   MarkSweep::adjust_pointer(k->adr_subklass());
   MarkSweep::adjust_pointer(k->adr_next_sibling());
   return size;
--- a/src/share/vm/oops/methodKlass.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/oops/methodKlass.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -102,6 +102,7 @@
   m->invocation_counter()->init();
   m->backedge_counter()->init();
   m->clear_number_of_breakpoints();
+  m->set_graal_mirror(NULL);
 
 #ifdef TIERED
   m->set_rate(0);
@@ -127,6 +128,7 @@
   // know that Universe::methodKlassObj never moves.
   MarkSweep::mark_and_push(m->adr_constMethod());
   MarkSweep::mark_and_push(m->adr_constants());
+  MarkSweep::mark_and_push(m->adr_graal_mirror());
   if (m->method_data() != NULL) {
     MarkSweep::mark_and_push(m->adr_method_data());
   }
@@ -141,6 +143,7 @@
   // know that Universe::methodKlassObj never moves.
   PSParallelCompact::mark_and_push(cm, m->adr_constMethod());
   PSParallelCompact::mark_and_push(cm, m->adr_constants());
+  PSParallelCompact::mark_and_push(cm, m->adr_graal_mirror());
 #ifdef COMPILER2
   if (m->method_data() != NULL) {
     PSParallelCompact::mark_and_push(cm, m->adr_method_data());
@@ -159,6 +162,7 @@
   // know that Universe::methodKlassObj never moves
   blk->do_oop(m->adr_constMethod());
   blk->do_oop(m->adr_constants());
+  blk->do_oop(m->adr_graal_mirror());
   if (m->method_data() != NULL) {
     blk->do_oop(m->adr_method_data());
   }
@@ -179,6 +183,8 @@
   if (mr.contains(adr)) blk->do_oop(adr);
   adr = m->adr_constants();
   if (mr.contains(adr)) blk->do_oop(adr);
+  adr = m->adr_graal_mirror();
+  if (mr.contains(adr)) blk->do_oop(adr);
   if (m->method_data() != NULL) {
     adr = m->adr_method_data();
     if (mr.contains(adr)) blk->do_oop(adr);
@@ -197,6 +203,7 @@
   // know that Universe::methodKlassObj never moves.
   MarkSweep::adjust_pointer(m->adr_constMethod());
   MarkSweep::adjust_pointer(m->adr_constants());
+  MarkSweep::adjust_pointer(m->adr_graal_mirror());
   if (m->method_data() != NULL) {
     MarkSweep::adjust_pointer(m->adr_method_data());
   }
@@ -213,6 +220,7 @@
   methodOop m = methodOop(obj);
   PSParallelCompact::adjust_pointer(m->adr_constMethod());
   PSParallelCompact::adjust_pointer(m->adr_constants());
+  PSParallelCompact::adjust_pointer(m->adr_graal_mirror());
 #ifdef COMPILER2
   if (m->method_data() != NULL) {
     PSParallelCompact::adjust_pointer(m->adr_method_data());
--- a/src/share/vm/oops/methodOop.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/oops/methodOop.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -206,6 +206,12 @@
 }
 
 address methodOopDesc::bcp_from(int bci) const {
+#ifdef ASSERT
+  if (!((is_native() && bci == 0)  || (!is_native() && 0 <= bci && bci < code_size()))) {
+    char buf[1024];
+    tty->print_cr("bci: %i, size: %i, method: %s", bci, code_size(), const_cast<methodOop>(this)->name_and_sig_as_C_string(buf, 1024));
+  }
+#endif // ASSERT
   assert((is_native() && bci == 0)  || (!is_native() && 0 <= bci && bci < code_size()), "illegal bci");
   address bcp = code_base() + bci;
   assert(is_native() && bcp == code_base() || contains(bcp), "bcp doesn't belong to this method");
--- a/src/share/vm/oops/methodOop.hpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/oops/methodOop.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -129,6 +129,8 @@
   InvocationCounter _invocation_counter;         // Incremented before each activation of the method - used to trigger frequency-based optimizations
   InvocationCounter _backedge_counter;           // Incremented before each backedge taken - used to trigger frequencey-based optimizations
 
+  // com/oracle/max/graal/runtime/HotSpotMethodResolved mirroring this method
+  oop               _graal_mirror;
 #ifdef TIERED
   jlong             _prev_time;                   // Previous time the rate was acquired
   float             _rate;                        // Events (invocation and backedge counter increments) per millisecond
@@ -328,6 +330,10 @@
   int invocation_count();
   int backedge_count();
 
+  // graal mirror
+  oop graal_mirror() const               { return _graal_mirror; }
+  void set_graal_mirror(oop m)           { oop_store((oop*) &_graal_mirror, m); }
+
   bool was_executed_more_than(int n);
   bool was_never_executed()                      { return !was_executed_more_than(0); }
 
@@ -716,6 +722,7 @@
   // Garbage collection support
   oop*  adr_constMethod() const                  { return (oop*)&_constMethod;     }
   oop*  adr_constants() const                    { return (oop*)&_constants;       }
+  oop*  adr_graal_mirror() const                 { return (oop*)&_graal_mirror;    }
   oop*  adr_method_data() const                  { return (oop*)&_method_data;     }
 };
 
--- a/src/share/vm/prims/jni.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/prims/jni.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -29,6 +29,7 @@
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
 #include "interpreter/linkResolver.hpp"
+#include "graal/graalCompiler.hpp"
 #ifndef SERIALGC
 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
 #endif // SERIALGC
@@ -3367,6 +3368,11 @@
     if (JvmtiExport::should_post_thread_life()) {
        JvmtiExport::post_thread_start(thread);
     }
+
+    if (BootstrapGraal) {
+      CompileBroker::bootstrap_graal();
+    }
+
     // Check if we should compile all classes on bootclasspath
     NOT_PRODUCT(if (CompileTheWorld) ClassLoader::compile_the_world();)
     // Since this is not a JVM_ENTRY we have to set the thread state manually before leaving.
--- a/src/share/vm/prims/jvmtiCodeBlobEvents.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/prims/jvmtiCodeBlobEvents.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -251,7 +251,7 @@
 
     address scopes_data = nm->scopes_data_begin();
     for( pcd = nm->scopes_pcs_begin(); pcd < nm->scopes_pcs_end(); ++pcd ) {
-      ScopeDesc sc0(nm, pcd->scope_decode_offset(), pcd->should_reexecute(), pcd->return_oop());
+      ScopeDesc sc0(nm, pcd->scope_decode_offset(), pcd->should_reexecute(), pcd->rethrow_exception(), pcd->return_oop());
       ScopeDesc *sd  = &sc0;
       while( !sd->is_top() ) { sd = sd->sender(); }
       int bci = sd->bci();
--- a/src/share/vm/runtime/arguments.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/runtime/arguments.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -67,6 +67,8 @@
 int     Arguments::_num_jvm_flags               = 0;
 char**  Arguments::_jvm_args_array              = NULL;
 int     Arguments::_num_jvm_args                = 0;
+char**  Arguments::_graal_args_array              = NULL;
+int     Arguments::_num_graal_args                = 0;
 char*  Arguments::_java_command                 = NULL;
 SystemProperty* Arguments::_system_properties   = NULL;
 const char*  Arguments::_gc_log_filename        = NULL;
@@ -753,6 +755,10 @@
   add_string(&_jvm_flags_array, &_num_jvm_flags, arg);
 }
 
+void Arguments::add_graal_arg(const char* arg) {
+  add_string(&_graal_args_array, &_num_graal_args, arg);
+}
+
 // utility function to return a string that concatenates all
 // strings in a given char** array
 const char* Arguments::build_resource_string(char** args, int count) {
@@ -2667,6 +2673,48 @@
           return JNI_EINVAL;
         }
       }
+    } else if (match_option(option, "-graal", &tail)) {
+      if (PrintVMOptions) {
+        tty->print("Running Graal VM... ");
+      }
+      UseGraal = true;
+      BootstrapGraal = true;
+      const int BUFFER_SIZE = 1024;
+      char maxine_dir[BUFFER_SIZE];
+      char graal_dir[BUFFER_SIZE];
+      char temp[BUFFER_SIZE];
+      if (!os::getenv("MAXINE", maxine_dir, sizeof(maxine_dir))) {
+        fatal("Must set MAXINE environment variable to a Maxine project directory.");
+      }
+      if (PrintVMOptions) tty->print("MAXINE=%s", maxine_dir);
+      if (!os::getenv("GRAAL", graal_dir, sizeof(graal_dir))) {
+        fatal("Must set GRAAL environment variable to a Graal project directory.");
+      }
+      if (PrintVMOptions) tty->print_cr(" GRAAL=%s", graal_dir);
+      sprintf(temp, "%s/com.oracle.max.cri/bin", maxine_dir);
+      scp_p->add_prefix(temp);
+      sprintf(temp, "%s/com.oracle.max.base/bin", maxine_dir);
+      scp_p->add_prefix(temp);
+      sprintf(temp, "%s/com.oracle.max.asmdis/bin", maxine_dir);
+      scp_p->add_prefix(temp);
+      sprintf(temp, "%s/com.oracle.max.asm/bin", maxine_dir);
+      scp_p->add_prefix(temp);
+      sprintf(temp, "%s/com.oracle.max.graal.graph/bin", maxine_dir);
+      scp_p->add_prefix(temp);
+      sprintf(temp, "%s/graal/com.oracle.max.graal.compiler/bin", graal_dir);
+      scp_p->add_prefix(temp);
+      sprintf(temp, "%s/graal/com.oracle.max.graal.runtime/bin", graal_dir);
+      scp_p->add_prefix(temp);
+      sprintf(temp, "%s/graal/com.oracle.max.graal.graphviz/bin", graal_dir);
+      scp_p->add_prefix(temp);
+      *scp_assembly_required_p = true;
+    } else if (match_option(option, "-G:", &tail)) { // -G:XXX
+      // Option for the graal compiler.
+      if (PrintVMOptions) {
+        tty->print_cr("graal option %s", tail);
+      }
+      Arguments::add_graal_arg(tail);
+
     // Unknown option
     } else if (is_bad_option(option, args->ignoreUnrecognized)) {
       return JNI_ERR;
--- a/src/share/vm/runtime/arguments.hpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/runtime/arguments.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -228,6 +228,9 @@
   // an array containing all jvm arguments specified in the command line
   static char** _jvm_args_array;
   static int    _num_jvm_args;
+  // an array containing all graal arguments specified in the command line
+  static char** _graal_args_array;
+  static int    _num_graal_args;
   // string containing all java command (class/jarfile name and app args)
   static char* _java_command;
 
@@ -366,6 +369,7 @@
   // methods to build strings from individual args
   static void build_jvm_args(const char* arg);
   static void build_jvm_flags(const char* arg);
+  static void add_graal_arg(const char* arg);
   static void add_string(char*** bldarray, int* count, const char* arg);
   static const char* build_resource_string(char** args, int count);
 
@@ -421,7 +425,9 @@
   // return a char* array containing all options
   static char** jvm_flags_array()          { return _jvm_flags_array; }
   static char** jvm_args_array()           { return _jvm_args_array; }
+  static char** graal_args_array()           { return _graal_args_array; }
   static int num_jvm_flags()               { return _num_jvm_flags; }
+  static int num_graal_args()               { return _num_graal_args; }
   static int num_jvm_args()                { return _num_jvm_args; }
   // return the arguments passed to the Java application
   static const char* java_command()        { return _java_command; }
--- a/src/share/vm/runtime/deoptimization.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/runtime/deoptimization.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -177,6 +177,10 @@
   // the vframeArray is created.
   //
 
+  if (TraceDeoptimization) {
+    tty->print_cr("fetching unroll info");
+  }
+
   // Allocate our special deoptimization ResourceMark
   DeoptResourceMark* dmark = new DeoptResourceMark(thread);
   assert(thread->deopt_mark() == NULL, "Pending deopt!");
@@ -208,11 +212,11 @@
   assert(vf->is_compiled_frame(), "Wrong frame type");
   chunk->push(compiledVFrame::cast(vf));
 
-#ifdef COMPILER2
+//#ifdef COMPILER2
   // Reallocate the non-escaping objects and restore their fields. Then
   // relock objects if synchronization on them was eliminated.
-  if (DoEscapeAnalysis) {
-    if (EliminateAllocations) {
+//  if (DoEscapeAnalysis) {
+//    if (EliminateAllocations) {
       assert (chunk->at(0)->scope() != NULL,"expect only compiled java frames");
       GrowableArray<ScopeValue*>* objects = chunk->at(0)->scope()->objects();
 
@@ -256,8 +260,8 @@
         // Restore result.
         deoptee.set_saved_oop_result(&map, return_value());
       }
-    }
-    if (EliminateLocks) {
+//    }
+//    if (EliminateLocks) {
 #ifndef PRODUCT
       bool first = true;
 #endif
@@ -284,9 +288,9 @@
 #endif
         }
       }
-    }
-  }
-#endif // COMPILER2
+//    }
+//  }
+//#endif // COMPILER2
   // Ensure that no safepoint is taken after pointers have been stored
   // in fields of rematerialized objects.  If a safepoint occurs from here on
   // out the java state residing in the vframeArray will be missed.
@@ -734,7 +738,7 @@
 }
 
 
-#ifdef COMPILER2
+//#ifdef COMPILER2
 bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, GrowableArray<ScopeValue*>* objects, TRAPS) {
   Handle pending_exception(thread->pending_exception());
   const char* exception_file = thread->exception_file();
@@ -914,6 +918,9 @@
     KlassHandle k(((ConstantOopReadValue*) sv->klass())->value()());
     Handle obj = sv->value();
     assert(obj.not_null(), "reallocation was missed");
+    if (TraceDeoptimization) {
+      tty->print_cr("reassign fields for object of type %s!", k->name()->as_C_string());
+    }
 
     if (k->oop_is_instance()) {
       instanceKlass* ik = instanceKlass::cast(k());
@@ -976,7 +983,7 @@
   }
 }
 #endif
-#endif // COMPILER2
+//#endif // COMPILER2
 
 vframeArray* Deoptimization::create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray<compiledVFrame*>* chunk) {
 
@@ -1177,7 +1184,6 @@
 JRT_END
 
 
-#if defined(COMPILER2) || defined(SHARK)
 void Deoptimization::load_class_by_index(constantPoolHandle constant_pool, int index, TRAPS) {
   // in case of an unresolved klass entry, load the class.
   if (constant_pool->tag_at(index).is_unresolved_klass()) {
@@ -1247,17 +1253,35 @@
     DeoptAction action = trap_request_action(trap_request);
     jint unloaded_class_index = trap_request_index(trap_request); // CP idx or -1
 
+//    tty->print_cr("trap_request: %08x, cpi: %i, pc: %016x", trap_request, unloaded_class_index, fr.pc());
+
+    
     Events::log("Uncommon trap occurred @" INTPTR_FORMAT " unloaded_class_index = %d", fr.pc(), (int) trap_request);
     vframe*  vf  = vframe::new_vframe(&fr, &reg_map, thread);
     compiledVFrame* cvf = compiledVFrame::cast(vf);
-
+    
     nmethod* nm = cvf->code();
+    ScopeDesc*      trap_scope  = cvf->scope();
+    
+    if (TraceDeoptimization) {
+      tty->print_cr("Deoptimization: bci=%d pc=%d, relative_pc=%d, method=%s", trap_scope->bci(), fr.pc(), fr.pc() - nm->code_begin(), trap_scope->method()->name()->as_C_string());
+    }
 
-    ScopeDesc*      trap_scope  = cvf->scope();
     methodHandle    trap_method = trap_scope->method();
     int             trap_bci    = trap_scope->bci();
     Bytecodes::Code trap_bc     = trap_method->java_code_at(trap_bci);
 
+    if (trap_scope->rethrow_exception()) {
+      if (TraceDeoptimization) {
+        tty->print_cr("Exception to be rethrown in the interpreter for method %s::%s at bci %d", instanceKlass::cast(trap_method->method_holder())->name()->as_C_string(), trap_method->name()->as_C_string(), trap_bci);
+      }
+      GrowableArray<ScopeValue*>* expressions = trap_scope->expressions();
+      guarantee(expressions != NULL, "must have exception to throw");
+      ScopeValue* topOfStack = expressions->top();
+      Handle topOfStackObj = cvf->create_stack_value(topOfStack)->get_obj();
+      THREAD->set_pending_exception(topOfStackObj(), NULL, 0);
+    }
+    
     // Record this event in the histogram.
     gather_statistics(reason, action, trap_bc);
 
@@ -1919,40 +1943,3 @@
     if (xtty != NULL)  xtty->tail("statistics");
   }
 }
-#else // COMPILER2 || SHARK
-
-
-// Stubs for C1 only system.
-bool Deoptimization::trap_state_is_recompiled(int trap_state) {
-  return false;
-}
-
-const char* Deoptimization::trap_reason_name(int reason) {
-  return "unknown";
-}
-
-void Deoptimization::print_statistics() {
-  // no output
-}
-
-void
-Deoptimization::update_method_data_from_interpreter(methodDataHandle trap_mdo, int trap_bci, int reason) {
-  // no udpate
-}
-
-int Deoptimization::trap_state_has_reason(int trap_state, int reason) {
-  return 0;
-}
-
-void Deoptimization::gather_statistics(DeoptReason reason, DeoptAction action,
-                                       Bytecodes::Code bc) {
-  // no update
-}
-
-const char* Deoptimization::format_trap_state(char* buf, size_t buflen,
-                                              int trap_state) {
-  jio_snprintf(buf, buflen, "#%d", trap_state);
-  return buf;
-}
-
-#endif // COMPILER2 || SHARK
--- a/src/share/vm/runtime/deoptimization.hpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/runtime/deoptimization.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -110,7 +110,7 @@
   // executing in a particular CodeBlob if UseBiasedLocking is enabled
   static void revoke_biases_of_monitors(CodeBlob* cb);
 
-#ifdef COMPILER2
+//#ifdef COMPILER2
   // Support for restoring non-escaping objects
   static bool realloc_objects(JavaThread* thread, frame* fr, GrowableArray<ScopeValue*>* objects, TRAPS);
   static void reassign_type_array_elements(frame* fr, RegisterMap* reg_map, ObjectValue* sv, typeArrayOop obj, BasicType type);
@@ -118,7 +118,7 @@
   static void reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray<ScopeValue*>* objects);
   static void relock_objects(GrowableArray<MonitorInfo*>* monitors, JavaThread* thread);
   NOT_PRODUCT(static void print_objects(GrowableArray<ScopeValue*>* objects);)
-#endif // COMPILER2
+//#endif // COMPILER2
 
   public:
   static vframeArray* create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray<compiledVFrame*>* chunk);
--- a/src/share/vm/runtime/globals.hpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/runtime/globals.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -848,6 +848,9 @@
   diagnostic(bool, LogCompilation, false,                                   \
           "Log compilation activity in detail to hotspot.log or LogFile")   \
                                                                             \
+  product(intx, MaxCompilationID, -1,                                       \
+          "All methods with greater compilation ID are skipped")            \
+                                                                            \
   product(bool, PrintCompilation, false,                                    \
           "Print compilations")                                             \
                                                                             \
@@ -1271,7 +1274,7 @@
   develop(bool, TraceClassInitialization, false,                            \
           "Trace class initialization")                                     \
                                                                             \
-  develop(bool, TraceExceptions, false,                                     \
+  product(bool, TraceExceptions, false,                                     \
           "Trace exceptions")                                               \
                                                                             \
   develop(bool, TraceICs, false,                                            \
@@ -2878,7 +2881,7 @@
           "Prefetch instruction to prefetch ahead")                         \
                                                                             \
   /* deoptimization */                                                      \
-  develop(bool, TraceDeoptimization, false,                                 \
+  product(bool, TraceDeoptimization, false,                                 \
           "Trace deoptimization")                                           \
                                                                             \
   develop(bool, DebugDeoptimization, false,                                 \
@@ -3702,7 +3705,7 @@
           "Skip assert() and verify() which page-in unwanted shared "       \
           "objects. ")                                                      \
                                                                             \
-  diagnostic(bool, EnableInvokeDynamic, true,                               \
+  diagnostic(bool, EnableInvokeDynamic, false,                              \
           "support JSR 292 (method handles, invokedynamic, "                \
           "anonymous classes")                                              \
                                                                             \
--- a/src/share/vm/runtime/java.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/runtime/java.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -30,6 +30,7 @@
 #include "compiler/compileBroker.hpp"
 #include "compiler/compilerOracle.hpp"
 #include "interpreter/bytecodeHistogram.hpp"
+#include "graal/graalCompiler.hpp"
 #include "memory/genCollectedHeap.hpp"
 #include "memory/oopFactory.hpp"
 #include "memory/universe.hpp"
@@ -418,6 +419,10 @@
   #define BEFORE_EXIT_DONE    2
   static jint volatile _before_exit_status = BEFORE_EXIT_NOT_RUN;
 
+  if (UseGraal) {
+    GraalCompiler::instance()->exit();
+  }
+
   // Note: don't use a Mutex to guard the entire before_exit(), as
   // JVMTI post_thread_end_event and post_vm_death_event will run native code.
   // A CAS or OSMutex would work just fine but then we need to manipulate
--- a/src/share/vm/runtime/javaCalls.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/runtime/javaCalls.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -58,7 +58,8 @@
 
   guarantee(thread->is_Java_thread(), "crucial check - the VM thread cannot and must not escape to Java code");
   assert(!thread->owns_locks(), "must release all locks when leaving VM");
-  guarantee(!thread->is_Compiler_thread(), "cannot make java calls from the compiler");
+  // (tw) may we do this?
+  // guarantee(!thread->is_Compiler_thread(), "cannot make java calls from the compiler");
   _result   = result;
 
   // Allocate handle block for Java code. This must be done before we change thread_state to _thread_in_Java_or_stub,
@@ -198,6 +199,23 @@
   }
 }
 
+// ============ Interface calls ============
+
+void JavaCalls::call_interface(JavaValue* result, KlassHandle spec_klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) {
+  CallInfo callinfo;
+  Handle receiver = args->receiver();
+  KlassHandle recvrKlass(THREAD, receiver.is_null() ? (klassOop)NULL : receiver->klass());
+  LinkResolver::resolve_interface_call(
+          callinfo, receiver, recvrKlass, spec_klass, name, signature,
+          KlassHandle(), false, true, CHECK);
+  methodHandle method = callinfo.selected_method();
+  assert(method.not_null(), "should have thrown exception");
+
+  // Invoke the method
+  JavaCalls::call(result, method, args, CHECK);
+}
+
+
 // ============ Virtual calls ============
 
 void JavaCalls::call_virtual(JavaValue* result, KlassHandle spec_klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) {
@@ -352,7 +370,8 @@
 #endif
 
 
-  assert(!thread->is_Compiler_thread(), "cannot compile from the compiler");
+  // (tw) may we do this?
+  //assert(!thread->is_Compiler_thread(), "cannot compile from the compiler");
   if (CompilationPolicy::must_be_compiled(method)) {
     CompileBroker::compile_method(method, InvocationEntryBci,
                                   CompLevel_initial_compile,
--- a/src/share/vm/runtime/javaCalls.hpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/runtime/javaCalls.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -201,6 +201,12 @@
   static void call_special(JavaValue* result, Handle receiver, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS);
   static void call_special(JavaValue* result, Handle receiver, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS);
 
+  // interface call
+  // ------------
+
+  // The receiver must be first oop in argument list
+  static void call_interface(JavaValue* result, KlassHandle spec_klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS);
+
   // virtual call
   // ------------
 
--- a/src/share/vm/runtime/sharedRuntime.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/runtime/sharedRuntime.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -707,8 +707,15 @@
 
 #ifdef COMPILER1
   if (t == NULL && nm->is_compiled_by_c1()) {
-    assert(nm->unwind_handler_begin() != NULL, "");
-    return nm->unwind_handler_begin();
+    if (UseGraal) {
+      nm->make_not_entrant();
+      JavaThread::current()->set_exception_pc(ret_pc);
+      JavaThread::current()->set_exception_oop(exception());
+      return SharedRuntime::deopt_blob()->unpack_with_exception_in_tls();
+    } else {
+      assert(nm->unwind_handler_begin() != NULL, "");
+      return nm->unwind_handler_begin();
+    }
   }
 #endif
 
@@ -763,6 +770,15 @@
   throw_and_post_jvmti_exception(thread, exception);
 JRT_END
 
+address SharedRuntime::deoptimization_continuation(JavaThread* thread, address pc, nmethod* nm)
+{
+  if (TraceSignals) {
+    tty->print_cr(err_msg("Deoptimizing on implicit exception at relative pc=%d in method %s", pc - nm->entry_point(), nm->method()->name()->as_C_string()));
+  }
+  thread->_ScratchA = (intptr_t)pc;
+  return (SharedRuntime::deopt_blob()->jmp_uncommon_trap());
+}
+
 JRT_ENTRY(void, SharedRuntime::throw_WrongMethodTypeException(JavaThread* thread, oopDesc* required, oopDesc* actual))
   assert(thread == JavaThread::current() && required->is_oop() && actual->is_oop(), "bad args");
   ResourceMark rm;
@@ -776,6 +792,10 @@
 {
   address target_pc = NULL;
 
+  if (TraceSignals) {
+    tty->print_cr("Searching for continuation for implicit exception at %d!", pc);
+  }
+
   if (Interpreter::contains(pc)) {
 #ifdef CC_INTERP
     // C++ interpreter doesn't throw implicit exceptions
@@ -850,7 +870,11 @@
 #ifndef PRODUCT
           _implicit_null_throws++;
 #endif
-          target_pc = nm->continuation_for_implicit_exception(pc);
+          if (UseGraal) {
+            target_pc = deoptimization_continuation(thread, pc, nm);
+          } else {
+            target_pc = nm->continuation_for_implicit_exception(pc);
+          }
           // If there's an unexpected fault, target_pc might be NULL,
           // in which case we want to fall through into the normal
           // error handling code.
@@ -866,7 +890,14 @@
 #ifndef PRODUCT
         _implicit_div0_throws++;
 #endif
-        target_pc = nm->continuation_for_implicit_exception(pc);
+        if (UseGraal) {
+          if (TraceSignals) {
+            tty->print_cr("graal implicit div0");
+          }
+          target_pc = deoptimization_continuation(thread, pc, nm);
+        } else {
+          target_pc = nm->continuation_for_implicit_exception(pc);
+        }
         // If there's an unexpected fault, target_pc might be NULL,
         // in which case we want to fall through into the normal
         // error handling code.
@@ -2730,7 +2761,7 @@
   // ResourceObject, so do not put any ResourceMarks in here.
   char *s = sig->as_C_string();
   int len = (int)strlen(s);
-  *s++; len--;                  // Skip opening paren
+  s++; len--;                  // Skip opening paren
   char *t = s+len;
   while( *(--t) != ')' ) ;      // Find close paren
 
--- a/src/share/vm/runtime/sharedRuntime.hpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/runtime/sharedRuntime.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -185,6 +185,7 @@
   static void    throw_NullPointerException(JavaThread* thread);
   static void    throw_NullPointerException_at_call(JavaThread* thread);
   static void    throw_StackOverflowError(JavaThread* thread);
+  static address deoptimization_continuation(JavaThread* thread, address pc, nmethod* nm);
   static void    throw_WrongMethodTypeException(JavaThread* thread, oopDesc* required, oopDesc* actual);
   static address continuation_for_implicit_exception(JavaThread* thread,
                                                      address faulting_pc,
--- a/src/share/vm/runtime/stackValue.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/runtime/stackValue.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -118,6 +118,22 @@
          val = (oop)NULL;
       }
 #endif
+#ifndef PRODUCT
+      if (val != NULL && !val->is_oop()) {
+        ResourceMark rm;
+        tty->print_cr("found wrong oop " INTPTR_FORMAT " at location " INTPTR_FORMAT " (%d):", val, value_addr, val->is_oop());
+        if (fr->cb() != NULL) {
+          CodeBlob* cb = fr->cb();
+          if (cb->is_nmethod()) {
+            nmethod* nm = (nmethod*)cb;
+            tty->print_cr("method is %s", nm->method()->name()->as_C_string());
+          }
+        }
+        sv->print();
+        tty->print_cr("");
+        tty->print_cr("one less %d; one more %d", (*(((oop *)value_addr) - 1))->is_oop(), (*(((oop *)value_addr) + 1))->is_oop());
+      }
+#endif
       Handle h(val); // Wrap a handle around the oop
       return new StackValue(h);
     }
--- a/src/share/vm/runtime/thread.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/runtime/thread.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -29,6 +29,7 @@
 #include "classfile/vmSymbols.hpp"
 #include "code/scopeDesc.hpp"
 #include "compiler/compileBroker.hpp"
+#include "graal/graalCompiler.hpp"
 #include "interpreter/interpreter.hpp"
 #include "interpreter/linkResolver.hpp"
 #include "interpreter/oopMapCache.hpp"
@@ -1984,7 +1985,9 @@
 
   // Do not throw asynchronous exceptions against the compiler thread
   // (the compiler thread should not be a Java thread -- fix in 1.4.2)
-  if (is_Compiler_thread()) return;
+
+  // (tw) May we do this?
+  //if (is_Compiler_thread()) return;
 
   {
     // Actually throw the Throwable against the target Thread - however
@@ -2942,6 +2945,7 @@
   _task  = NULL;
   _queue = queue;
   _counters = counters;
+  _is_compiling = false;
   _buffer_blob = NULL;
   _scanned_nmethod = NULL;
 
@@ -3917,7 +3921,9 @@
   {
     MutexLockerEx ml(doLock ? Threads_lock : NULL);
     ALL_JAVA_THREADS(p) {
-      if (p->is_Compiler_thread()) continue;
+      
+      // (tw) May we do this?
+      //if (p->is_Compiler_thread()) continue;
 
       address pending = (address)p->current_pending_monitor();
       if (pending == monitor) {             // found a match
--- a/src/share/vm/runtime/thread.hpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/runtime/thread.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -833,6 +833,9 @@
 
  private:
 
+  // graal needs some place to put the dimensions
+  jint graal_multinewarray_storage[256];
+
   StackGuardState        _stack_guard_state;
 
   // Compiler exception handling (NOTE: The _exception_oop is *NOT* the same as _pending_exception. It is
@@ -1268,6 +1271,7 @@
   static ByteSize is_method_handle_return_offset() { return byte_offset_of(JavaThread, _is_method_handle_return); }
   static ByteSize stack_guard_state_offset()     { return byte_offset_of(JavaThread, _stack_guard_state   ); }
   static ByteSize suspend_flags_offset()         { return byte_offset_of(JavaThread, _suspend_flags       ); }
+  static ByteSize graal_multinewarray_storage_offset() { return byte_offset_of(JavaThread, graal_multinewarray_storage); }
 
   static ByteSize do_not_unlock_if_synchronized_offset() { return byte_offset_of(JavaThread, _do_not_unlock_if_synchronized); }
   static ByteSize should_post_on_exceptions_flag_offset() {
@@ -1696,6 +1700,7 @@
   CompileLog*   _log;
   CompileTask*  _task;
   CompileQueue* _queue;
+  bool          _is_compiling;
   BufferBlob*   _buffer_blob;
 
   nmethod*      _scanned_nmethod;  // nmethod being scanned by the sweeper
@@ -1706,6 +1711,8 @@
 
   CompilerThread(CompileQueue* queue, CompilerCounters* counters);
 
+  bool is_compiling() const                      { return _is_compiling; }
+  void set_compiling(bool b)                     { _is_compiling = b; }
   bool is_Compiler_thread() const                { return true; }
   // Hide this compiler thread from external view.
   bool is_hidden_from_external_view() const      { return true; }
--- a/src/share/vm/runtime/vframe.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/runtime/vframe.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -570,6 +570,14 @@
     if (size > 4*K) warning("SUSPICIOUSLY LARGE FRAME (%d)", size);
 #endif
   }
+
+  tty->print_cr("");
+  int i = -1;
+  for (intptr_t* a = _fr.sp() - 1; a <= _fr.fp(); a++) {
+    oop o = (oop)(*a);
+    tty->print_cr("sp[%d] = " INTPTR_FORMAT " (%d)", i, *a, o->is_oop());
+    ++i;
+  }
 }
 
 
--- a/src/share/vm/runtime/vframeArray.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/runtime/vframeArray.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "classfile/vmSymbols.hpp"
+#include "code/scopeDesc.hpp"
 #include "interpreter/interpreter.hpp"
 #include "memory/allocation.inline.hpp"
 #include "memory/resourceArea.hpp"
@@ -62,7 +63,7 @@
   _method = vf->method();
   _bci    = vf->raw_bci();
   _reexecute = vf->should_reexecute();
-
+  
   int index;
 
   // Get the monitors off-stack
@@ -126,28 +127,37 @@
 
   // Now the expressions off-stack
   // Same silliness as above
-
-  StackValueCollection *exprs = vf->expressions();
-  _expressions = new StackValueCollection(exprs->size());
-  for(index = 0; index < exprs->size(); index++) {
-    StackValue* value = exprs->at(index);
-    switch(value->type()) {
-      case T_OBJECT:
-        assert(!value->obj_is_scalar_replaced(), "object should be reallocated already");
-        // preserve object type
-        _expressions->add( new StackValue((intptr_t) (value->get_obj()()), T_OBJECT ));
-        break;
-      case T_CONFLICT:
-        // A dead stack element.  Will be initialized to null/zero.
-        // This can occur when the compiler emits a state in which stack
-        // elements are known to be dead (because of an imminent exception).
-        _expressions->add( new StackValue());
-        break;
-      case T_INT:
-        _expressions->add( new StackValue(value->get_int()));
-        break;
-      default:
-        ShouldNotReachHere();
+  bool rethrow_exception = vf->scope()->rethrow_exception();
+  if (rethrow_exception) {
+    // (tw) Make sure there are only null pointers on the stack, because the stack values do not correspond to the GC map at the bytecode at which the exception is rethrown.
+    _expressions = new StackValueCollection(vf->method()->max_stack());
+    assert(Thread::current()->has_pending_exception(), "just checking");
+    for (int i=0; i<vf->method()->max_stack(); ++i) {
+      _expressions->add( new StackValue());
+    }
+  } else {
+    StackValueCollection *exprs = vf->expressions();
+    _expressions = new StackValueCollection(exprs->size());
+    for(index = 0; index < exprs->size(); index++) {
+      StackValue* value = exprs->at(index);
+      switch(value->type()) {
+        case T_OBJECT:
+          assert(!value->obj_is_scalar_replaced(), "object should be reallocated already");
+          // preserve object type
+          _expressions->add( new StackValue((intptr_t) (value->get_obj()()), T_OBJECT ));
+          break;
+        case T_CONFLICT:
+          // A dead stack element.  Will be initialized to null/zero.
+          // This can occur when the compiler emits a state in which stack
+          // elements are known to be dead (because of an imminent exception).
+          _expressions->add( new StackValue());
+          break;
+        case T_INT:
+          _expressions->add( new StackValue(value->get_int()));
+          break;
+        default:
+          ShouldNotReachHere();
+      }
     }
   }
 }
@@ -306,22 +316,41 @@
       iframe()->interpreter_frame_set_mdp(mdp);
     }
   }
+  
+  if (TraceDeoptimization) {
+    tty->print_cr("Expressions size: %d", expressions()->size());
+  }
 
   // Unpack expression stack
   // If this is an intermediate frame (i.e. not top frame) then this
   // only unpacks the part of the expression stack not used by callee
   // as parameters. The callee parameters are unpacked as part of the
   // callee locals.
-  int i;
-  for(i = 0; i < expressions()->size(); i++) {
+  for(int i = 0; i < expressions()->size(); i++) {
     StackValue *value = expressions()->at(i);
     intptr_t*   addr  = iframe()->interpreter_frame_expression_stack_at(i);
     switch(value->type()) {
       case T_INT:
         *addr = value->get_int();
+#ifndef PRODUCT
+        if (TraceDeoptimization) {
+          tty->print_cr("Reconstructed expression %d (INT): %d", i, (int)(*addr));
+        }
+#endif
         break;
       case T_OBJECT:
         *addr = value->get_int(T_OBJECT);
+#ifndef PRODUCT
+        if (TraceDeoptimization) {
+          tty->print("Reconstructed expression %d (OBJECT): ", i);
+          oop o = (oop)(*addr);
+          if (o == NULL) {
+            tty->print_cr("NULL");
+          } else {
+            tty->print_cr(err_msg("%s", o->blueprint()->name()->as_C_string()));
+          }
+        }
+#endif
         break;
       case T_CONFLICT:
         // A dead stack slot.  Initialize to null in case it is an oop.
@@ -334,15 +363,31 @@
 
 
   // Unpack the locals
-  for(i = 0; i < locals()->size(); i++) {
+  for(int i = 0; i < locals()->size(); i++) {
     StackValue *value = locals()->at(i);
     intptr_t* addr  = iframe()->interpreter_frame_local_at(i);
     switch(value->type()) {
       case T_INT:
         *addr = value->get_int();
+#ifndef PRODUCT
+        if (TraceDeoptimization) {
+          tty->print_cr("Reconstructed local %d (INT): %d", i, (int)(*addr));
+        }
+#endif
         break;
       case T_OBJECT:
         *addr = value->get_int(T_OBJECT);
+#ifndef PRODUCT
+        if (TraceDeoptimization) {
+          tty->print("Reconstructed local %d (OBJECT): ", i);
+          oop o = (oop)(*addr);
+          if (o == NULL) {
+            tty->print_cr("NULL");
+          } else {
+            tty->print_cr(err_msg("%s", o->blueprint()->name()->as_C_string()));
+          }
+        }
+#endif
         break;
       case T_CONFLICT:
         // A dead location. If it is an oop then we need a NULL to prevent GC from following it
--- a/src/share/vm/runtime/vframe_hp.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/runtime/vframe_hp.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -70,6 +70,12 @@
     }
   }
 
+  if (TraceDeoptimization) {
+    tty->print_cr("bci=%d length=%d", this->bci(), length);
+    tty->print_cr(err_msg("method name = %s", this->method()->name()->as_C_string()));
+    tty->print_cr("relative pc=%d", this->fr().pc() - this->nm()->code_begin());
+  }
+
   for( int i = 0; i < length; i++ ) {
     result->add( create_stack_value(scv_list->at(i)) );
   }
--- a/src/share/vm/runtime/vframe_hp.hpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/runtime/vframe_hp.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -66,7 +66,7 @@
   // Returns SynchronizationEntryBCI or bci() (used for synchronization)
   int raw_bci() const;
 
- protected:
+ //protected:
   ScopeDesc* _scope;
 
 
--- a/src/share/vm/runtime/vm_version.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/runtime/vm_version.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -118,7 +118,7 @@
   #define VMTYPE "Zero"
 #endif // SHARK
 #else // ZERO
-   #define VMTYPE COMPILER1_PRESENT("Client")   \
+   #define VMTYPE COMPILER1_PRESENT("Graal")   \
                   COMPILER2_PRESENT("Server")
 #endif // ZERO
 #endif // TIERED
--- a/src/share/vm/utilities/exceptions.cpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/utilities/exceptions.cpp	Wed Jul 27 17:32:44 2011 -0700
@@ -92,7 +92,8 @@
 #endif // ASSERT
 
   if (thread->is_VM_thread()
-      || thread->is_Compiler_thread() ) {
+	  // (tw) May we do this?
+      /*|| thread->is_Compiler_thread()*/ ) {
     // We do not care what kind of exception we get for the vm-thread or a thread which
     // is compiling.  We just install a dummy exception object
     thread->set_pending_exception(Universe::vm_exception(), file, line);
@@ -115,7 +116,8 @@
   }
 
   if (thread->is_VM_thread()
-      || thread->is_Compiler_thread() ) {
+	  // (tw) May we do this?
+     /* || thread->is_Compiler_thread()*/ ) {
     // We do not care what kind of exception we get for the vm-thread or a thread which
     // is compiling.  We just install a dummy exception object
     thread->set_pending_exception(Universe::vm_exception(), file, line);
--- a/src/share/vm/utilities/globalDefinitions.hpp	Tue Jun 28 10:57:38 2011 -0700
+++ b/src/share/vm/utilities/globalDefinitions.hpp	Wed Jul 27 17:32:44 2011 -0700
@@ -102,9 +102,9 @@
 // log2_intptr(sizeof(class JavaThread)) - log2_intptr(64);
 // see os::set_memory_serialize_page()
 #ifdef _LP64
-const int SerializePageShiftCount = 4;
+const int SerializePageShiftCount = 5;
 #else
-const int SerializePageShiftCount = 3;
+const int SerializePageShiftCount = 4;
 #endif
 
 // An opaque struct of heap-word width, so that HeapWord* can be a generic