changeset 2507:9ec15d6914ca

Pull over of compiler from maxine repository.
author Thomas Wuerthinger <thomas@wuerthinger.net>
date Wed, 27 Apr 2011 11:43:22 +0200
parents 4a3bf8a5bf41
children fea94949e0a2
files graal/Compiler/.checkstyle graal/Compiler/.checkstyle_checks.xml graal/Compiler/.classpath graal/Compiler/.project graal/Compiler/.settings/JavaSourceCodeFormatting.xml graal/Compiler/.settings/org.eclipse.jdt.core.prefs graal/Compiler/.settings/org.eclipse.jdt.ui.prefs graal/Compiler/LICENSE graal/Compiler/bin/com/sun/c1x/doc/IRInterpreter.txt graal/Compiler/bin/com/sun/c1x/doc/LoopPeeling.txt graal/Compiler/bin/com/sun/c1x/doc/backend_open_issues.txt graal/Compiler/bin/com/sun/c1x/doc/differences.txt graal/Compiler/bin/com/sun/c1x/doc/performance.txt graal/Compiler/src/com/sun/c1x/C1XCompilation.java graal/Compiler/src/com/sun/c1x/C1XCompiler.java graal/Compiler/src/com/sun/c1x/C1XCompilerExtension.java graal/Compiler/src/com/sun/c1x/C1XIntrinsic.java graal/Compiler/src/com/sun/c1x/C1XMetrics.java graal/Compiler/src/com/sun/c1x/C1XOptions.java graal/Compiler/src/com/sun/c1x/C1XTimers.java graal/Compiler/src/com/sun/c1x/alloc/ControlFlowOptimizer.java graal/Compiler/src/com/sun/c1x/alloc/EdgeMoveOptimizer.java graal/Compiler/src/com/sun/c1x/alloc/Interval.java graal/Compiler/src/com/sun/c1x/alloc/IntervalWalker.java graal/Compiler/src/com/sun/c1x/alloc/LIRInsertionBuffer.java graal/Compiler/src/com/sun/c1x/alloc/LinearScan.java graal/Compiler/src/com/sun/c1x/alloc/LinearScanWalker.java graal/Compiler/src/com/sun/c1x/alloc/MoveResolver.java graal/Compiler/src/com/sun/c1x/alloc/OperandPool.java graal/Compiler/src/com/sun/c1x/alloc/Range.java graal/Compiler/src/com/sun/c1x/alloc/RegisterVerifier.java graal/Compiler/src/com/sun/c1x/asm/AbstractAssembler.java graal/Compiler/src/com/sun/c1x/asm/Buffer.java graal/Compiler/src/com/sun/c1x/asm/ExceptionInfo.java graal/Compiler/src/com/sun/c1x/asm/Label.java graal/Compiler/src/com/sun/c1x/debug/BlockPrinter.java graal/Compiler/src/com/sun/c1x/debug/CFGPrinter.java graal/Compiler/src/com/sun/c1x/debug/CFGPrinterObserver.java graal/Compiler/src/com/sun/c1x/debug/InstructionPrinter.java graal/Compiler/src/com/sun/c1x/debug/LogStream.java graal/Compiler/src/com/sun/c1x/debug/TTY.java graal/Compiler/src/com/sun/c1x/debug/package-info.java graal/Compiler/src/com/sun/c1x/doc/IRInterpreter.txt graal/Compiler/src/com/sun/c1x/doc/LoopPeeling.txt graal/Compiler/src/com/sun/c1x/doc/backend_open_issues.txt graal/Compiler/src/com/sun/c1x/doc/differences.txt graal/Compiler/src/com/sun/c1x/doc/performance.txt graal/Compiler/src/com/sun/c1x/gen/LIRGenerator.java graal/Compiler/src/com/sun/c1x/gen/LIRItem.java graal/Compiler/src/com/sun/c1x/gen/PhiResolver.java graal/Compiler/src/com/sun/c1x/gen/package-info.java graal/Compiler/src/com/sun/c1x/globalstub/GlobalStub.java graal/Compiler/src/com/sun/c1x/globalstub/GlobalStubEmitter.java graal/Compiler/src/com/sun/c1x/graph/BlockMap.java graal/Compiler/src/com/sun/c1x/graph/BlockUtil.java graal/Compiler/src/com/sun/c1x/graph/CriticalEdgeFinder.java graal/Compiler/src/com/sun/c1x/graph/GraphBuilder.java graal/Compiler/src/com/sun/c1x/graph/IR.java graal/Compiler/src/com/sun/c1x/graph/MemoryMap.java graal/Compiler/src/com/sun/c1x/graph/ScopeData.java graal/Compiler/src/com/sun/c1x/graph/package-info.java graal/Compiler/src/com/sun/c1x/ir/AccessArray.java graal/Compiler/src/com/sun/c1x/ir/AccessField.java graal/Compiler/src/com/sun/c1x/ir/AccessIndexed.java graal/Compiler/src/com/sun/c1x/ir/AccessMonitor.java graal/Compiler/src/com/sun/c1x/ir/ArithmeticOp.java graal/Compiler/src/com/sun/c1x/ir/ArrayCopy.java graal/Compiler/src/com/sun/c1x/ir/ArrayLength.java graal/Compiler/src/com/sun/c1x/ir/Base.java graal/Compiler/src/com/sun/c1x/ir/BlockBegin.java graal/Compiler/src/com/sun/c1x/ir/BlockClosure.java graal/Compiler/src/com/sun/c1x/ir/BlockEnd.java graal/Compiler/src/com/sun/c1x/ir/BlockList.java graal/Compiler/src/com/sun/c1x/ir/BoundsCheck.java graal/Compiler/src/com/sun/c1x/ir/BreakpointTrap.java graal/Compiler/src/com/sun/c1x/ir/CheckCast.java graal/Compiler/src/com/sun/c1x/ir/CompareAndSwap.java graal/Compiler/src/com/sun/c1x/ir/CompareOp.java graal/Compiler/src/com/sun/c1x/ir/ComputeLinearScanOrder.java graal/Compiler/src/com/sun/c1x/ir/Condition.java graal/Compiler/src/com/sun/c1x/ir/Constant.java graal/Compiler/src/com/sun/c1x/ir/Convert.java graal/Compiler/src/com/sun/c1x/ir/DefaultValueVisitor.java graal/Compiler/src/com/sun/c1x/ir/ExceptionHandler.java graal/Compiler/src/com/sun/c1x/ir/ExceptionObject.java graal/Compiler/src/com/sun/c1x/ir/Goto.java graal/Compiler/src/com/sun/c1x/ir/Guard.java graal/Compiler/src/com/sun/c1x/ir/IRScope.java graal/Compiler/src/com/sun/c1x/ir/If.java graal/Compiler/src/com/sun/c1x/ir/IfOp.java graal/Compiler/src/com/sun/c1x/ir/IncrementRegister.java graal/Compiler/src/com/sun/c1x/ir/Info.java graal/Compiler/src/com/sun/c1x/ir/Infopoint.java graal/Compiler/src/com/sun/c1x/ir/InstanceOf.java graal/Compiler/src/com/sun/c1x/ir/Instruction.java graal/Compiler/src/com/sun/c1x/ir/Intrinsic.java graal/Compiler/src/com/sun/c1x/ir/Invoke.java graal/Compiler/src/com/sun/c1x/ir/LoadField.java graal/Compiler/src/com/sun/c1x/ir/LoadIndexed.java graal/Compiler/src/com/sun/c1x/ir/LoadPointer.java graal/Compiler/src/com/sun/c1x/ir/LoadRegister.java graal/Compiler/src/com/sun/c1x/ir/Local.java graal/Compiler/src/com/sun/c1x/ir/LogicOp.java graal/Compiler/src/com/sun/c1x/ir/LookupSwitch.java graal/Compiler/src/com/sun/c1x/ir/MemoryBarrier.java graal/Compiler/src/com/sun/c1x/ir/MonitorAddress.java graal/Compiler/src/com/sun/c1x/ir/MonitorEnter.java graal/Compiler/src/com/sun/c1x/ir/MonitorExit.java graal/Compiler/src/com/sun/c1x/ir/NativeCall.java graal/Compiler/src/com/sun/c1x/ir/NegateOp.java graal/Compiler/src/com/sun/c1x/ir/NewArray.java graal/Compiler/src/com/sun/c1x/ir/NewInstance.java graal/Compiler/src/com/sun/c1x/ir/NewMultiArray.java graal/Compiler/src/com/sun/c1x/ir/NewObjectArray.java graal/Compiler/src/com/sun/c1x/ir/NewObjectArrayClone.java graal/Compiler/src/com/sun/c1x/ir/NewTypeArray.java graal/Compiler/src/com/sun/c1x/ir/NullCheck.java graal/Compiler/src/com/sun/c1x/ir/Op2.java graal/Compiler/src/com/sun/c1x/ir/OsrEntry.java graal/Compiler/src/com/sun/c1x/ir/Pause.java graal/Compiler/src/com/sun/c1x/ir/Phi.java graal/Compiler/src/com/sun/c1x/ir/PointerOp.java graal/Compiler/src/com/sun/c1x/ir/ResolveClass.java graal/Compiler/src/com/sun/c1x/ir/Return.java graal/Compiler/src/com/sun/c1x/ir/ShiftOp.java graal/Compiler/src/com/sun/c1x/ir/SignificantBitOp.java graal/Compiler/src/com/sun/c1x/ir/StackAllocate.java graal/Compiler/src/com/sun/c1x/ir/StackHandle.java graal/Compiler/src/com/sun/c1x/ir/StateSplit.java graal/Compiler/src/com/sun/c1x/ir/StoreField.java graal/Compiler/src/com/sun/c1x/ir/StoreIndexed.java graal/Compiler/src/com/sun/c1x/ir/StorePointer.java graal/Compiler/src/com/sun/c1x/ir/StoreRegister.java graal/Compiler/src/com/sun/c1x/ir/Switch.java graal/Compiler/src/com/sun/c1x/ir/TableSwitch.java graal/Compiler/src/com/sun/c1x/ir/TemplateCall.java graal/Compiler/src/com/sun/c1x/ir/Throw.java graal/Compiler/src/com/sun/c1x/ir/TypeCheck.java graal/Compiler/src/com/sun/c1x/ir/TypeEqualityCheck.java graal/Compiler/src/com/sun/c1x/ir/UnsafeCast.java graal/Compiler/src/com/sun/c1x/ir/UnsafeGetObject.java graal/Compiler/src/com/sun/c1x/ir/UnsafeGetRaw.java graal/Compiler/src/com/sun/c1x/ir/UnsafeObjectOp.java graal/Compiler/src/com/sun/c1x/ir/UnsafeOp.java graal/Compiler/src/com/sun/c1x/ir/UnsafePrefetch.java graal/Compiler/src/com/sun/c1x/ir/UnsafePrefetchRead.java graal/Compiler/src/com/sun/c1x/ir/UnsafePrefetchWrite.java graal/Compiler/src/com/sun/c1x/ir/UnsafePutObject.java graal/Compiler/src/com/sun/c1x/ir/UnsafePutRaw.java graal/Compiler/src/com/sun/c1x/ir/UnsafeRawOp.java graal/Compiler/src/com/sun/c1x/ir/UnsignedCompareOp.java graal/Compiler/src/com/sun/c1x/ir/Value.java graal/Compiler/src/com/sun/c1x/ir/ValueClosure.java graal/Compiler/src/com/sun/c1x/ir/ValueVisitor.java graal/Compiler/src/com/sun/c1x/ir/package-info.java graal/Compiler/src/com/sun/c1x/lir/FrameMap.java graal/Compiler/src/com/sun/c1x/lir/LIRAssembler.java graal/Compiler/src/com/sun/c1x/lir/LIRBlock.java graal/Compiler/src/com/sun/c1x/lir/LIRBranch.java graal/Compiler/src/com/sun/c1x/lir/LIRCall.java graal/Compiler/src/com/sun/c1x/lir/LIRCompareAndSwap.java graal/Compiler/src/com/sun/c1x/lir/LIRConvert.java graal/Compiler/src/com/sun/c1x/lir/LIRDebugInfo.java graal/Compiler/src/com/sun/c1x/lir/LIRInstruction.java graal/Compiler/src/com/sun/c1x/lir/LIRLabel.java graal/Compiler/src/com/sun/c1x/lir/LIRList.java graal/Compiler/src/com/sun/c1x/lir/LIRMemoryBarrier.java graal/Compiler/src/com/sun/c1x/lir/LIRMonitorAddress.java graal/Compiler/src/com/sun/c1x/lir/LIRNegate.java graal/Compiler/src/com/sun/c1x/lir/LIROp0.java graal/Compiler/src/com/sun/c1x/lir/LIROp1.java graal/Compiler/src/com/sun/c1x/lir/LIROp2.java graal/Compiler/src/com/sun/c1x/lir/LIROp3.java graal/Compiler/src/com/sun/c1x/lir/LIROpcode.java graal/Compiler/src/com/sun/c1x/lir/LIROperand.java graal/Compiler/src/com/sun/c1x/lir/LIRSignificantBit.java graal/Compiler/src/com/sun/c1x/lir/LIRStackAllocate.java graal/Compiler/src/com/sun/c1x/lir/LIRTableSwitch.java graal/Compiler/src/com/sun/c1x/lir/LIRXirInstruction.java graal/Compiler/src/com/sun/c1x/lir/package-info.java graal/Compiler/src/com/sun/c1x/observer/CompilationEvent.java graal/Compiler/src/com/sun/c1x/observer/CompilationObserver.java graal/Compiler/src/com/sun/c1x/observer/ObservableCompiler.java graal/Compiler/src/com/sun/c1x/observer/package-info.java graal/Compiler/src/com/sun/c1x/opt/BlockMerger.java graal/Compiler/src/com/sun/c1x/opt/CEEliminator.java graal/Compiler/src/com/sun/c1x/opt/Canonicalizer.java graal/Compiler/src/com/sun/c1x/opt/GlobalValueNumberer.java graal/Compiler/src/com/sun/c1x/opt/InstructionSubstituter.java graal/Compiler/src/com/sun/c1x/opt/LivenessMarker.java graal/Compiler/src/com/sun/c1x/opt/NullCheckEliminator.java graal/Compiler/src/com/sun/c1x/opt/PhiSimplifier.java graal/Compiler/src/com/sun/c1x/opt/SCCPropagator.java graal/Compiler/src/com/sun/c1x/opt/TypeAnalyzer.java graal/Compiler/src/com/sun/c1x/opt/UnsafeCastEliminator.java graal/Compiler/src/com/sun/c1x/opt/ValueMap.java graal/Compiler/src/com/sun/c1x/package-info.java graal/Compiler/src/com/sun/c1x/target/Backend.java graal/Compiler/src/com/sun/c1x/target/amd64/AMD64.java graal/Compiler/src/com/sun/c1x/target/amd64/AMD64Assembler.java graal/Compiler/src/com/sun/c1x/target/amd64/AMD64Backend.java graal/Compiler/src/com/sun/c1x/target/amd64/AMD64GlobalStubEmitter.java graal/Compiler/src/com/sun/c1x/target/amd64/AMD64LIRAssembler.java graal/Compiler/src/com/sun/c1x/target/amd64/AMD64LIRGenerator.java graal/Compiler/src/com/sun/c1x/target/amd64/AMD64MacroAssembler.java graal/Compiler/src/com/sun/c1x/target/amd64/AMD64XirAssembler.java graal/Compiler/src/com/sun/c1x/target/sparc/SPARC.java graal/Compiler/src/com/sun/c1x/util/ArrayMap.java graal/Compiler/src/com/sun/c1x/util/BitMap2D.java graal/Compiler/src/com/sun/c1x/util/BlockWorkList.java graal/Compiler/src/com/sun/c1x/util/IntList.java graal/Compiler/src/com/sun/c1x/util/Util.java graal/Compiler/src/com/sun/c1x/value/FrameState.java graal/Compiler/src/com/sun/c1x/value/MutableFrameState.java graal/Compiler/src/com/sun/c1x/value/package-info.java
diffstat 215 files changed, 47388 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/.checkstyle	Wed Apr 27 11:43:22 2011 +0200
@@ -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/Compiler/.checkstyle_checks.xml	Wed Apr 27 11:43:22 2011 +0200
@@ -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/Compiler/.classpath	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,7 @@
+<?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" exported="true" kind="src" path="/CRI"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/.project	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>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/Compiler/.settings/JavaSourceCodeFormatting.xml	Wed Apr 27 11:43:22 2011 +0200
@@ -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/Compiler/.settings/org.eclipse.jdt.core.prefs	Wed Apr 27 11:43:22 2011 +0200
@@ -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/Compiler/.settings/org.eclipse.jdt.ui.prefs	Wed Apr 27 11:43:22 2011 +0200
@@ -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/Compiler/LICENSE	Wed Apr 27 11:43:22 2011 +0200
@@ -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/Compiler/bin/com/sun/c1x/doc/IRInterpreter.txt	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,26 @@
+Current status and remaining issues in the IRInterpreter for HIR (September/18/09)
+=================================================================================
+
+Known Problems:
+With InterpretInvokedMethods disabled in C1XOptions:
+(2 fails)
+304: jtt/jvmni/JVM_GetClassContext01.java: (0) failed with false (expected true)
+557: jtt/reflect/Class_newInstance02.java: (0) failed with true (expected !java.lang.IllegalAccessException)
+
+The first problem is caused by the use of reflection in the IRInterpreter, and the calling stack is not as 
+expected by the JVM_GetClassContext01 test case. The second one is due to the private constructor of Class_newInstance01.
+Again, we are using reflection to call the newInstance() method to create an instance of class Class_newInstance01
+from the IRInterpreter class, which raises an IllegalAccessException.
+These are the only problems with all optimization levels.
+
+With InterpretInvokedMethods enabled in C1XOptions:
+(7 fails)
+245: jtt/except/Catch_StackOverflowError_03.java: (0) failed with !java.lang.InstantiationException (expected 0)
+304: jtt/jvmni/JVM_GetClassContext01.java: (0) failed with false (expected true)
+311: jtt/lang/Bridge_method01.java: (0) failed with unexpected com.sun.c1x.ci.CiBailout (expected 1)
+557: jtt/reflect/Class_newInstance02.java: (0) failed with true (expected !java.lang.IllegalAccessException)
+572: jtt/reflect/Invoke_virtual01.java: (1) failed with unexpected com.sun.c1x.ci.CiBailout (expected 55)
+575: jtt/reflect/Reflection_getCallerClass01.java: (1) failed with com.sun.c1x.debug.IRInterpreter$Evaluator (expected jtt.reflect.Reflection_getCallerClass01$Caller1)
+592: jtt/threads/Thread_isInterrupted04.java: (0) failed with false (expected true)
+
+Those are also due to reflection usage. The last problem has not been investigated.
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/bin/com/sun/c1x/doc/LoopPeeling.txt	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,43 @@
+Remaining Issues in the Loop Peeling optimization (September/18/09)
+===================================================================
+
+Known Problems:
+Currently loop peeling is not working when the loop has exception
+blocks. The algorithm has to be updated to handle these cases.
+
+Limitations:
+The algorithm performs loop peeling only on innermost loops. However,
+this is not a limitation. If one wants to peel the outermost loop(s),
+after peeling the innermost loop, an additional pass is necessary
+to update the blocks of the outermost loop, since after peeling
+the innermost loop, newer blocks are added to the CFG.
+
+Current status as of 09/18/2009
+After running using hir configuration, with optimization level 3, the
+following test cases produce wrong results:
+(4 fails)
+233: jtt/except/Catch_Loop01.java: (4) failed with unexpected com.sun.c1x.ci.CiBailout (expected -170)
+234: jtt/except/Catch_Loop02.java: (4) failed with unexpected com.sun.c1x.ci.CiBailout (expected -170)
+245: jtt/except/Catch_StackOverflowError_03.java: (0) failed with unexpected com.sun.c1x.ci.CiBailout (expected 0)
+272: jtt/hotpath/HP_array04.java: (80) failed with unexpected java.lang.AssertionError (expected 15645)
+
+All of them are related the known problem aforementioned.
+All the tests have the innermost loops peeled, and produce right results.
+
+Future Work:
+1- Add more loop tests to jtt. New tests should run the loop 0, 1, 2 or more iterations.
+
+2- Peel loops with exception blocks. 
+
+3- Currently, all innermost loops are peeled. Should we add logic to filter out some loops from loop peeling?
+
+4- Improve the way instructions are cloned. Now the algorithm visits the blocks in BFS order, which
+might produce errors depending on the order the blocks are visited.
+
+5- After inserting new phi instructions at exit blocks, we need to iterate over the remaining CFG to update instructions
+that may use the new phi. The way it's done now might me inefficient if the block has more than one exit node, since
+we can iterate over the same block more than once. This needs to be improved.
+
+5- For performance reasons, improve the way loops are represented, for example, to use a bitmap to represent the loop blocks.
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/bin/com/sun/c1x/doc/backend_open_issues.txt	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,22 @@
+Remaining Issues in the C1X backend (after the port July-Sep 09)
+======================================================================
+
+Maxine/Inspector Related Open Issues:
+   - Global stubs: Change calling convention (no longer write to callee stack as this makes stepping through the instructions for saving the parameters to global stubs impossible in the inspector)
+   - Reference maps: Corrently implement TargetMethod.prepareReferenceMap for C1XTargetMethod (checking for the need to stack walk a possible callee saved target method) and call it from Maxine
+   - Disassembler: The Maxine disassembler still does not correctly display every machine code instruction issued by C1X
+   - MaxRiRuntime and C1XTargetMethod have fixed dependencies on the X86 parts (instruction decoding, registers, calling convention), should be factored out
+
+Compile-Time Performance Improvements:
+   - Consider deleting the LIRItem class
+   - Make sure that LIROperand objects are not shared among LIR instructions and can therefore be directly modified by the LinearScan register allocator (no more need for the lazy creation of LIRAddress objects in the LIRInstruction class)
+   
+Run-Time Performance Improvements:
+   - Store mapping between machine code location and bytecode index in the target method (remove arguments from global stub calls), this decreases the number of necessary parameters especially for resolution instructions.
+   - Use Inline Cache on virtual method calls
+
+Better Portability:
+   - Integrate XIR; consider using CiLocation / CiConstant in XIR
+   - The JIT adapter frames should be a more general mechanism that receives two calling conventions (in form of an array of locations) and adapts between them automatically
+   - Have the possibility to register intrinsics by specifying XIR code
+   
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/bin/com/sun/c1x/doc/differences.txt	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,154 @@
+Differences between C1 and C1X, including upgrades and limitations
+(and some general information about C1)
+======================================================================
+
+StrictFP:
+   - C1X has removed the backend code to deal with the FPU stack, and therefore
+     requires SSE2 currently. StrictFP is still tracked in the front end.
+   - C1 will not inline methods with different strictfp-ness. C1X does not have this
+     limitation because it only targets SSE2 x86 processors.
+
+JSR/RET
+   - C1 will bail out if it encounters strange JSR/RET patterns
+       - recursive JSRs
+       - JSR regions that are shared with non-JSR code
+       - RET encountered out of JSR (would not verify)
+
+Exceptions
+   -  C1 will bailout if the code of an exception handler can be reached via normal
+      control flow.
+   => C1X might be extended to introduce a phi for the exception
+      object in this case.
+   -  C1 will bailout if an exception handler covers itself
+
+Verification
+   -  C1 does not rely on bytecode verification having been run. However, if it detects
+      type errors in its building the IR graph it will usually bail out.
+   -  C1 requires a bitmap of the bytecode, where a bit for
+      each byte of the bytecode indicates if the bytecode at that location starts a
+      basic block. It uses this to construct the basic block list in a single pass.
+   => Assertion failures and/or bugs in C1X that cause exceptions to be thrown bail out
+      the compilation instead of crashing the VM.
+   => C1X's BlockMap does not computes the basic block starts in one pass over the bytecode
+      and one pass over the successor lists.
+   => C1X computes the "stores in loops" only when loops are encountered in the CFG.
+      An option can select conservative mode (all locals stored in all loops) trades
+      faster parse speed for fewer optimization opportunities
+   => C1X includes an IRChecker that typechecks the entire IR and checks for CFG
+      consistency that can be run after each pass.
+
+Constants
+   => C1X allows unrestricted use of object constants throughout the code, including
+      folding reads of static final fields that reference objects.
+
+Pinning
+   => C1X pins fewer instructions than C1
+   ** C1X will eventually allow certain kinds of instructions to float outside the CFG
+      and be scheduled with a C2-lite scheduling pass.
+
+Synchronization
+   -  C1 will refuse to compile methods with unbalanced synchronization. This property is
+      computed by the bytecode verifier and supplied to C1.
+   ** C1X will not rely on the bytecode verifier to compute this but should do so itself.
+   => C1 relied on the backend to generate synchronization code for the root method's
+      synchronization operations. C1X inserts code into the start block and generates
+      and exception handler to do this explicitly.
+
+Optimizations
+   => C1X has many more options to turn on individual passes, parts of passes, approximations,
+      etc. It is designed to have three optimization levels:
+      0 = super-fast: essentially no optimization
+      1 = fast:       inlining, constant folding, and local optimizations
+      2 = optimized:  inlining, constant folding, local and global optimizations, including
+                      iterative versions of all algorithms
+   ** Planned optimizations for C1X that C1 does not have:
+      TypeCheckElimination:        remove redundant casts and devirtualize more call sites
+      ArrayBoundsCheckElimination: remove redundant array bounds checks and/or restructure
+                                   code to deoptimize when bounds checks within loops will fail
+      LoopPeeling:                 replicate the first iteration of a loop
+      LoopUnrolling:               replicate the body of certain shapes of loops
+      LoopInvariantCodeMotion:     move invariant code out of a loop
+      ProfileGuidedInlining:       use receiver method profiles to emit guarded inlines
+      ProfileGuidedBlockLayout:    use profiling information for code placement
+      Peephole:                    peephole optimize backend output
+
+Block Merging
+   ** C1X will replace branches to blocks with a single Goto with a branch to the
+      block's successor, if the blocks cannot be merged otherwise.
+
+Constant Folding / Strength reduction
+   -  C1 had some of its strength reduction logic built into the GraphBuilder because
+      the Canonicalizer could not return multiple instructions.
+   => C1X added this ability, moved the logic to Canonicalizer, and added a few new
+      strength reductions.
+   => C1X should have an interface for doing folding of @FOLD method calls
+   => C1X folds many intrinsic operations that don't have side effects
+   => C1X folds all the basic floating point operations
+   => C1X strength reduces (e >> C >> K) to (e >> (C + K)) when C and K are constant
+   => Multiplies of power-of-2 constants are reduced to shifts in the canonicalizer
+      (instead of the backend)
+   ** C1X will be able to run a global sparse conditional constant propagation phase
+      to catch any missed canonicalization opportunities after graph building.
+
+Switches
+   -  C1 did not detect back edges in tableswitch/lookupswitch default branches
+   => C1X does detect these back edges
+   => C1X moved the canonicalization code of 1 and 2 branch switches to canonicalizer,
+      where it belongs
+
+Inlining
+   -  C1 cannot inline:
+      -  native methods (or their stubs), except some intrinsics
+      -  methods whose class has not been initialized
+      -  methods with unbalanced monitors
+      -  methods with JSRs (this is probably technically possible now)
+
+   -  C1 will not inline:
+      -  methods with exception handlers (optional)
+      -  synchronized methods (optional)
+      -  if the maximum inline depth is reached (default = 9)
+      -  if the maximum recursive inline depth is reached (default = 1)
+      -  if the callee is larger than the maximum inline size (reduced to 90% at each level, starting at 35)
+      -  constructors for subclasses of Throwable
+      -  if the strictfp-ness of the callee is different than the caller (on x87)
+      -  abstract methods
+      -  synchronized intrinsics
+
+Load/store elimination
+   => C1X may eliminate loads of static fields, which C1 did not
+   => C1X distinguishes loads/stores to different fields in MemoryBuffer
+   => C1X assumes that RiField instances are unique when .isLoaded() is true
+
+Local/Global Value Numbering
+   => C1X improved local load elimination and no longer value numbers fields, reducing the
+      logic necessary in ValueMap, simplifying it and improving its performance.
+   => C1X reuses the same simplified ValueMap for GVN. Since heap accesses are no longer
+      value numbered, the logic to kill values is unnecessary, greatly simplifying
+      GVN.
+   ** A global version of load elimination will compensate for this loss in the future.
+   => C1X value numbers are always or'd with a high order bit when value numbering is possible
+      to prevent value numbering failing if the value number is accidentally 0.
+
+Nullcheck elimination
+   => A new flag, NonNull, indicates instructions that produce values that are guaranteed
+      to be non-null (e.g. NewXXX and Local 0, NullCheck). Instructions that require null
+      checks check this flag for their inputs in their constructors, eliminating most
+      redundant null checks immediately, without requiring the NullCheckEliminator to run.
+   => C1X uses a more efficient block ordering for null check elimination. The first pass is
+      optimistic and attempts to visit the blocks in reverse post-order. For acyclic graphs,
+      this almost always succeeds, requiring no iteration. Full iterative data flow analysis
+      can be enabled separately. Bitmaps used during the fixpoint calculation are much
+      smaller due to local numbering of instructions (as opposed to global IDs).
+   ** C1X will recognize If's that check against null and propagate the non-nullness across
+      the appropriate branches.
+
+BlockListBuilder
+   -  C1 had a vestigial loop map in BlockListBuilder which was not really used.
+   => C1X does not need to compute a complete loop map in order to do selective phi creation,
+      it builds the "storesInLoops" BitMap in BlockMap.
+
+Types
+   => C1X adds the declared type of method parameters to Local instructions, which
+      may help with devirtualization
+   => C1X makes local 0 of instance methods non-null at the start
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/bin/com/sun/c1x/doc/performance.txt	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,85 @@
+Issues that can be addressed for improving performance in C1X
+----------------------------------------------------------------
+
+- indicates not done
+* indicates done
+
+Backend:
+	- better handling of constants, especially immediates
+	- (non XIR) checkcast, instanceof: use nullity
+	- (non XIR) checkcast, instanceof: emit fastpath direct compare
+	- use LEA instruction on x86
+	- recognize pointer arithmetic addressing modes
+	- recognize multiply by 3, 5, 9 and emit lea rk, [rs, rs*2], etc
+	- Maxine XIR: make direct runtime calls instead of through global stub
+	- Maxine XIR: implement inline allocation
+	- Maxine XIR: implement biased locking fastpath
+	- Maxine XIR: faster subtype checks for classes, leaves
+	- Maxine XIR: make use of XirSite nullity, range check information
+	- better handling of tableswitch bytecode
+	- better handling of two operand LIR form
+	- Make the following bytecode implementations inline:
+		- f2i f2l f2d d2i d2l d2f (SSE2)
+		* lrem ldiv (64 bit)
+		- fneg dneg
+	- Make the following bytecode implementations global stubs:
+		- frem drem
+	- Global stubs: use EAX for return value as normal instead of [rsp - 16]
+    - Emit direct call to runtime for new instance, monitorenter, monitorexit
+
+	* XIR: expose nullity, range checkness across XIR interface
+	- XIR: make use of CSE'd array length
+	- XIR: generate special if-instanceof XIR variant with label parameters
+    - Optimize special cases of bytecodes:
+        - (MIN_INT / -1) in IDIV,IREM
+        - (MIN_LONG / -1) in LDIV,LREM
+        - (-infinity, Nan, +infinity) in F2I, F2L, D2I, D2L
+
+
+Frontend:
+    - Remove redundant null check branches in NullCheckEliminator
+	- XIR: implement HIR -> HIR xir translation
+	- Refactor exception edges to allow removal, optimization
+	- Implement typecast elimination
+	- Implement constant propagation
+	- Implement GVN of memory loads / stores
+	- Implement memory reordering
+	- Implement loop invariant code motion
+	- Optimize endianness conversions and endian-writes
+	      (e.g. (x >> 24 & 0xff) | (....)) and a[0] = x >> 24 ...
+	- Finish loop peeling
+	- Implement loop unrolling
+	- Allow value numbering of constant loads
+	- Finish loop peeling
+	- Guarded and multiple inlining
+	- Maxine: speculative leaf class and leaf method assumption
+	- Maxine: adjust static / dynamic inlining heuristics
+		  (e.g. static: trivial methods only in cold spots)
+    - Aggressive optimization of array copy
+
+Compilation speed:
+    - Make special iterators for LIROperand input, temp, output
+    - Add analysisInfo field to Value and use in NullCheckEliminator
+	- Remove RiConstantPool, cpi from unresolved HIR instructions (move to RiField, RiMethod)
+	- Use BlockList instead of ArrayList<Block> where appropriate
+	- Use FrameState instead of ValueStack
+	- Remove exceptionHandlers, make DebugInfo hold FrameState, CiCodePos,
+		exception flags and exception handlers
+	- Clean up and simplify LIRInstruction constructor
+	- Create fewer LIRAddresses
+	- Simplify LIRGenerator logic (forcing of loading, etc)
+	- LIROperand: split into virtual register table?
+	- Cleanup assembler and remove dead code, useless assertions
+	- Chain assembler byte buffers and only assemble at the end
+	- Pick optimal initial assembler byte buffer size
+	- Pick good initial sizes for LinearScan data structures
+	- Remove unnecessary uses of ArrayList and replace with arrays or other list
+	- Use iteration over ArrayList instead of explicit loop
+	- Revisit manual editing / removal of items from ArrayList
+	- Remove non-XIR backend
+	- Pre-assemble XIR for backend
+
+	* Initialize compilation-unique instruction id's lazily with thread local compilation
+	* Remove dead LIROpcodes
+	* Remove dead code in LIRGenerator, X86LIRGenerator, LIRAssembler, X86LIRAssembler
+		(remove commented out code)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/C1XCompilation.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,354 @@
+/*
+ * 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.sun.c1x;
+
+import java.util.*;
+
+import com.sun.c1x.alloc.*;
+import com.sun.c1x.asm.*;
+import com.sun.c1x.gen.*;
+import com.sun.c1x.gen.LIRGenerator.DeoptimizationStub;
+import com.sun.c1x.graph.*;
+import com.sun.c1x.ir.*;
+import com.sun.c1x.lir.*;
+import com.sun.c1x.observer.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.bytecode.*;
+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.
+ *
+ * @author Ben L. Titzer
+ */
+public final class C1XCompilation {
+
+    private static ThreadLocal<C1XCompilation> currentCompilation = new ThreadLocal<C1XCompilation>();
+
+    public final C1XCompiler compiler;
+    public final CiTarget target;
+    public final RiRuntime runtime;
+    public final RiMethod method;
+    public final RiRegisterConfig registerConfig;
+    public final CiStatistics stats;
+    public final int osrBCI;
+    public final CiAssumptions assumptions = new CiAssumptions();
+    public final FrameState placeholderState;
+
+    private boolean hasExceptionHandlers;
+    private final C1XCompilation parent;
+
+    /**
+     * @see #setNotTypesafe()
+     * @see #isTypesafe()
+     */
+    private boolean typesafe = true;
+
+    private int nextID = 1;
+
+    private FrameMap frameMap;
+    private AbstractAssembler 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 C1XCompilation(C1XCompiler compiler, RiMethod method, int osrBCI, CiStatistics stats) {
+        this.parent = currentCompilation.get();
+        currentCompilation.set(this);
+        this.compiler = compiler;
+        this.target = compiler.target;
+        this.runtime = compiler.runtime;
+        this.method = method;
+        this.osrBCI = osrBCI;
+        this.stats = stats == null ? new CiStatistics() : stats;
+        this.registerConfig = method == null ? compiler.globalStubRegisterConfig : runtime.getRegisterConfig(method);
+        this.placeholderState = method != null && method.minimalDebugInfo() ? new MutableFrameState(new IRScope(null, null, method, -1), 0, 0, 0) : 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;
+    }
+
+    /**
+     * Records that this compilation encountered an instruction (e.g. {@link Bytecodes#UNSAFE_CAST})
+     * that breaks the type safety invariant of the input bytecode.
+     */
+    public void setNotTypesafe() {
+        typesafe = false;
+    }
+
+    /**
+     * Checks whether this compilation is for an on-stack replacement.
+     *
+     * @return {@code true} if this compilation is for an on-stack replacement
+     */
+    public boolean isOsrCompilation() {
+        return osrBCI >= 0;
+    }
+
+    /**
+     * 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);
+    }
+
+    /**
+     * Gets the frame which describes the layout of the OSR interpreter frame for this method.
+     *
+     * @return the OSR frame
+     */
+    public RiOsrFrame getOsrFrame() {
+        return runtime.getOsrFrame(method, osrBCI);
+    }
+
+    /**
+     * Records an assumption that the specified type has no finalizable subclasses.
+     *
+     * @param receiverType the type that is assumed to have no finalizable subclasses
+     * @return {@code true} if the assumption was recorded and can be assumed; {@code false} otherwise
+     */
+    public boolean recordNoFinalizableSubclassAssumption(RiType receiverType) {
+        return false;
+    }
+
+    /**
+     * Converts this compilation to a string.
+     *
+     * @return a string representation of this compilation
+     */
+    @Override
+    public String toString() {
+        if (isOsrCompilation()) {
+            return "osr-compile @ " + osrBCI + ": " + method;
+        }
+        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, int osrBCI) {
+        // PERF: cache the block map for methods that are compiled or inlined often
+        BlockMap map = new BlockMap(method, hir.numberOfBlocks());
+        boolean isOsrCompilation = false;
+        if (osrBCI >= 0) {
+            map.addEntrypoint(osrBCI, BlockBegin.BlockFlag.OsrEntry);
+            isOsrCompilation = true;
+        }
+        if (!map.build(!isOsrCompilation && C1XOptions.PhiLoopStores)) {
+            throw new CiBailout("build of BlockMap failed for " + method);
+        } else {
+            if (compiler.isObserved()) {
+                String label = CiUtil.format("BlockListBuilder %f %r %H.%n(%p)", method, true);
+                compiler.fireCompilationEvent(new CompilationEvent(this, label, map, method.code().length));
+            }
+        }
+        map.cleanup();
+        stats.bytecodeCount += map.numberOfBytes();
+        stats.blockCount += map.numberOfBlocks();
+        return map;
+    }
+
+    /**
+     * Returns the frame map of this compilation.
+     * @return the frame map
+     */
+    public FrameMap frameMap() {
+        return frameMap;
+    }
+
+    public AbstractAssembler masm() {
+        if (assembler == null) {
+            assembler = compiler.backend.newAssembler(registerConfig);
+            assembler.setFrameSize(frameMap.frameSize());
+            assembler.targetMethod.setCustomStackAreaOffset(frameMap.offsetToCustomArea());
+        }
+        return assembler;
+    }
+
+    public boolean hasExceptionHandlers() {
+        return hasExceptionHandlers;
+    }
+
+    /**
+     * Determines if this compilation has encountered any instructions (e.g. {@link Bytecodes#UNSAFE_CAST})
+     * that break the type safety invariant of the input bytecode.
+     */
+    public boolean isTypesafe() {
+        return typesafe;
+    }
+
+    public CiResult compile() {
+        CiTargetMethod targetMethod;
+        try {
+            emitHIR();
+            emitLIR();
+            targetMethod = emitCode();
+
+            if (C1XOptions.PrintMetrics) {
+                C1XMetrics.BytecodesCompiled += method.code().length;
+            }
+        } catch (CiBailout b) {
+            return new CiResult(null, b, stats);
+        } catch (Throwable t) {
+            return new CiResult(null, new CiBailout("Exception while compiling: " + method, t), stats);
+        } 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 (C1XOptions.GenLIR) {
+            if (C1XOptions.PrintTimers) {
+                C1XTimers.LIR_CREATE.start();
+            }
+
+            initFrameMap(hir.topScope.maxLocks());
+
+            lirGenerator = compiler.backend.newLIRGenerator(this);
+            for (BlockBegin begin : hir.linearScanOrder()) {
+                lirGenerator.doBlock(begin);
+            }
+
+            if (C1XOptions.PrintTimers) {
+                C1XTimers.LIR_CREATE.stop();
+            }
+
+            new LinearScan(this, hir, lirGenerator, frameMap()).allocate();
+        }
+    }
+
+    private CiTargetMethod emitCode() {
+        if (C1XOptions.GenLIR && C1XOptions.GenCode) {
+            final LIRAssembler lirAssembler = compiler.backend.newLIRAssembler(this);
+            lirAssembler.emitCode(hir.linearScanOrder());
+
+            // generate code for slow cases
+            lirAssembler.emitLocalStubs();
+
+            // generate exception adapters
+            lirAssembler.emitExceptionEntries();
+
+            // 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 = masm().finishTargetMethod(method, runtime, lirAssembler.registerRestoreEpilogueOffset, false);
+            if (assumptions.count() > 0) {
+                targetMethod.setAssumptions(assumptions);
+            }
+
+            if (compiler.isObserved()) {
+                compiler.fireCompilationEvent(new CompilationEvent(this, "After code generation", hir.startBlock, false, true, targetMethod));
+            }
+
+            if (C1XOptions.PrintTimers) {
+                C1XTimers.CODE_CREATE.stop();
+            }
+            return targetMethod;
+        }
+
+        return null;
+    }
+
+    public int nextID() {
+        return nextID++;
+    }
+
+    public static C1XCompilation compilation() {
+        C1XCompilation compilation = currentCompilation.get();
+        assert compilation != null;
+        return compilation;
+    }
+
+    public static C1XCompilation compilationOrNull() {
+        return currentCompilation.get();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/C1XCompiler.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,157 @@
+/*
+ * 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.sun.c1x;
+
+import java.util.*;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.globalstub.*;
+import com.sun.c1x.observer.*;
+import com.sun.c1x.target.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+import com.sun.cri.xir.*;
+
+/**
+ * This class implements the compiler interface for C1X.
+ *
+ * @author Thomas Wuerthinger
+ * @author Ben L. Titzer
+ */
+public class C1XCompiler 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 ordered set of compiler extensions.
+     */
+    public List<C1XCompilerExtension> extensions;
+
+    /**
+     * The backend that this compiler has been configured for.
+     */
+    public final Backend backend;
+
+    public final RiRegisterConfig globalStubRegisterConfig;
+
+    public C1XCompiler(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();
+    }
+
+    public CiResult compileMethod(RiMethod method, int osrBCI, RiXirGenerator xirGenerator, CiStatistics stats) {
+        long startTime = 0;
+        int index = C1XMetrics.CompiledMethods++;
+        if (C1XOptions.PrintCompilation) {
+            TTY.print(String.format("C1X %4d %-70s %-45s | ", index, method.holder().name(), method.name()));
+            startTime = System.nanoTime();
+        }
+
+        CiResult result = null;
+        TTY.Filter filter = new TTY.Filter(C1XOptions.PrintFilter, method);
+        C1XCompilation compilation = new C1XCompilation(this, method, osrBCI, stats);
+        try {
+            result = compilation.compile();
+        } finally {
+            filter.remove();
+            compilation.close();
+            if (C1XOptions.PrintCompilation && !TTY.isSuppressed()) {
+                long time = (System.nanoTime() - startTime) / 100000;
+                TTY.println(String.format("%3d.%dms", time / 10, time % 10));
+            }
+        }
+
+        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(C1XOptions.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(C1XOptions.PrintFilter, id);
+            try {
+                stubs.put(id, emitter.emit(id, runtime));
+            } finally {
+                suppressor.remove();
+            }
+        }
+
+        if (C1XOptions.PrintCFGToFile) {
+            addCompilationObserver(new CFGPrinterObserver());
+        }
+    }
+
+    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/Compiler/src/com/sun/c1x/C1XCompilerExtension.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,42 @@
+/*
+ * 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.c1x;
+
+import com.sun.c1x.graph.*;
+
+/**
+ * Mechanism for extending C1X with extra transformations, analysis, optimizations.
+ *
+ * TODO: add support for fine grain specification of where/when extensions are to be called
+ *
+ * @author Doug Simon
+ */
+public class C1XCompilerExtension {
+
+    public final void run(IR ir) {
+        process(ir);
+    }
+
+    protected void process(IR ir) {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/C1XIntrinsic.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,174 @@
+/*
+ * 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.sun.c1x;
+
+import java.util.*;
+
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * This enum represents all of the intrinsics, i.e. a library methods that
+ * are treated specially by the compiler. Note that the list includes more intrinsics
+ * than are currently handled by C1X.
+ *
+ * @author Ben L. Titzer
+ */
+public enum C1XIntrinsic {
+
+    // java.lang.Object
+    java_lang_Object$init     ("java.lang.Object", "<init>", "()V"),
+    java_lang_Object$hashCode ("java.lang.Object", "hashCode", "()I"),
+    java_lang_Object$getClass ("java.lang.Object", "getClass", "()Ljava/lang/Class;"),
+    java_lang_Object$clone    ("java.lang.Object", "clone", "()Ljava/lang/Object;"),
+
+    // java.lang.Class
+    java_lang_Class$isAssignableFrom ("java.lang.Class", "isAssignableFrom", "(Ljava/lang/Class;)Z"),
+    java_lang_Class$isInstance       ("java.lang.Class", "isInstance", "(Ljava/lang/Object;)Z"),
+    java_lang_Class$getModifiers     ("java.lang.Class", "getModifiers", "()I"),
+    java_lang_Class$isInterface      ("java.lang.Class", "isInterface", "()Z"),
+    java_lang_Class$isArray          ("java.lang.Class", "isArray", "()Z"),
+    java_lang_Class$isPrimitive      ("java.lang.Class", "isPrimitive", "()Z"),
+    java_lang_Class$getSuperclass    ("java.lang.Class", "getSuperclass", "()Ljava/lang/Class;"),
+    java_lang_Class$getComponentType ("java.lang.Class", "getComponentType", "()Ljava/lang/Class;"),
+
+    // java.util.Arrays
+    java_util_Arrays$copyOf ("java.util.Arrays", "copyOf", "([Ljava/lang/Object;I)[Ljava/lang/Object;"),
+
+    // java.lang.String
+    java_lang_String$compareTo ("java.lang.String", "compareTo", "(Ljava/lang/String;)I"),
+    java_lang_String$indexOf   ("java.lang.String", "indexOf", "(Ljava/lang/String;)I"),
+    java_lang_String$equals    ("java.lang.String", "equals", "(Ljava/lang/Object;)Z"),
+
+    // java.lang.Math
+    java_lang_Math$abs   ("java.lang.Math", "abs", "(D)D"),
+    java_lang_Math$sin   ("java.lang.Math", "sin", "(D)D"),
+    java_lang_Math$cos   ("java.lang.Math", "cos", "(D)D"),
+    java_lang_Math$tan   ("java.lang.Math", "tan", "(D)D"),
+    java_lang_Math$atan2 ("java.lang.Math", "atan2", "(DD)D"),
+    java_lang_Math$sqrt  ("java.lang.Math", "sqrt", "(D)D"),
+    java_lang_Math$log   ("java.lang.Math", "log", "(D)D"),
+    java_lang_Math$log10 ("java.lang.Math", "log10", "(D)D"),
+    java_lang_Math$pow   ("java.lang.Math", "pow", "(DD)D"),
+    java_lang_Math$exp   ("java.lang.Math", "exp", "(D)D"),
+    java_lang_Math$min   ("java.lang.Math", "min", "(II)I"),
+    java_lang_Math$max   ("java.lang.Math", "max", "(II)I"),
+
+    // java.lang.Float
+    java_lang_Float$floatToRawIntBits ("java.lang.Float", "floatToRawIntBits", "(F)I"),
+    java_lang_Float$floatToIntBits    ("java.lang.Float", "floatToIntBits", "(F)I"),
+    java_lang_Float$intBitsToFloat    ("java.lang.Float", "intBitsToFloat", "(I)F"),
+
+    // java.lang.Double
+    java_lang_Double$doubleToRawLongBits ("java.lang.Double", "doubleToRawLongBits", "(D)J"),
+    java_lang_Double$doubleToLongBits    ("java.lang.Double", "doubleToLongBits", "(D)J"),
+    java_lang_Double$longBitsToDouble    ("java.lang.Double", "longBitsToDouble", "(J)D"),
+
+    // java.lang.Integer
+    java_lang_Integer$bitCount     ("java.lang.Integer", "bitCount", "(I)I"),
+    java_lang_Integer$reverseBytes ("java.lang.Integer", "reverseBytes", "(I)I"),
+
+    // java.lang.Long
+    java_lang_Long$bitCount     ("java.lang.Long", "bitCount", "(J)I"),
+    java_lang_Long$reverseBytes ("java.lang.Long", "reverseBytes", "(J)J"),
+
+    // java.lang.System
+    java_lang_System$identityHashCode  ("java.lang.System", "identityHashCode", "(Ljava/lang/Object;)I"),
+    java_lang_System$currentTimeMillis ("java.lang.System", "currentTimeMillis", "()J"),
+    java_lang_System$nanoTime          ("java.lang.System", "nanoTime", "()J"),
+    java_lang_System$arraycopy         ("java.lang.System", "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V"),
+
+    // java.lang.Thread
+    java_lang_Thread$currentThread ("java.lang.Thread", "currentThread", "()Ljava/lang/Thread;"),
+
+    // java.lang.reflect.Array
+    java_lang_reflect_Array$getLength ("java.lang.reflect.Array", "getLength", "(Ljava/lang/Object;)I"),
+    java_lang_reflect_Array$newArray  ("java.lang.reflect.Array", "newArray", "(Ljava/lang/Class;I)Ljava/lang/Object;"),
+
+    // java.nio.Buffer
+    java_nio_Buffer$checkIndex ("java.nio.Buffer", "checkIndex", "(I)I"),
+
+    // sun.misc.Unsafe
+    sun_misc_Unsafe$compareAndSwapObject ("sun.misc.Unsafe", "compareAndSwapObject", "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z"),
+    sun_misc_Unsafe$compareAndSwapLong   ("sun.misc.Unsafe", "compareAndSwapLong", "(Ljava/lang/Object;JJJ)Z"),
+    sun_misc_Unsafe$compareAndSwapInt    ("sun.misc.Unsafe", "compareAndSwapInt", "(Ljava/lang/Object;JII)Z");
+
+    private static final HashMap<String, HashMap<String, C1XIntrinsic>> intrinsicMap = new HashMap<String, HashMap<String, C1XIntrinsic>>(100);
+
+    /**
+     * The name of the class in which this method is declared.
+     */
+    public final String className;
+
+    /**
+     * The name of this intrinsic method.
+     */
+    public final String methodName;
+
+    /**
+     * The signature of this intrinsic method as a string.
+     */
+    public final String signature;
+
+    C1XIntrinsic(String className, String methodName, String signature) {
+        // Check that enum names are according to convention.
+        assert className.equals(name().substring(0, name().indexOf('$')).replace('_', '.'));
+        assert methodName.equals("<init>") || methodName.equals(name().substring(name().indexOf('$') + 1));
+        this.methodName = methodName;
+        this.className = className;
+        this.signature = signature;
+    }
+
+    static {
+        // iterate through all the intrinsics and add them to the map
+        for (C1XIntrinsic i : C1XIntrinsic.values()) {
+            // note that the map uses internal names to map lookup faster
+            String className = CiUtil.toInternalName(i.className);
+            HashMap<String, C1XIntrinsic> map = intrinsicMap.get(className);
+            if (map == null) {
+                map = new HashMap<String, C1XIntrinsic>();
+                intrinsicMap.put(className, map);
+            }
+            map.put(i.methodName + i.signature, i);
+        }
+    }
+
+    /**
+     * Looks up an intrinsic for the specified method.
+     * @param method the compiler interface method
+     * @return a reference to the intrinsic for the method, if the method is an intrinsic
+     * (and is loaded); {@code null} otherwise
+     */
+    public static C1XIntrinsic getIntrinsic(RiMethod method) {
+        RiType holder = method.holder();
+        if (method.isResolved() && holder.isResolved() && holder.isInitialized()) {
+            // note that the map uses internal names to make lookup faster
+            HashMap<String, C1XIntrinsic> map = intrinsicMap.get(holder.name());
+            if (map != null) {
+                C1XIntrinsic result = map.get(method.name() + method.signature().asString());
+                return result;
+            }
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/C1XMetrics.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,149 @@
+/*
+ * 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.sun.c1x;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.sun.c1x.debug.*;
+
+
+/**
+ * This class contains a number of fields that collect metrics about compilation, particularly
+ * the number of times certain optimizations are performed.
+ *
+ * @author Ben L. Titzer
+ */
+public class C1XMetrics {
+    public static int CompiledMethods;
+    public static int TargetMethods;
+    public static int LocalValueNumberHits;
+    public static int GlobalValueNumberHits;
+    public static int ValueMapResizes;
+    public static int InlinedFinalizerChecks;
+    public static int MethodsFolded;
+    public static int InlineForcedMethods;
+    public static int InlineForbiddenMethods;
+    public static int InlinedJsrs;
+    public static int NullCheckIterations;
+    public static int NullCheckEliminations;
+    public static int NullChecksRedundant;
+    public static int NullCheckIdsAssigned;
+    public static int ZeroChecksRedundant;
+    public static int DivideSpecialChecksRedundant;
+    public static int StoreCheckEliminations;
+    public static int BoundsChecksElminations;
+    public static int ConditionalEliminations;
+    public static int BlocksMerged;
+    public static int BlocksSkipped;
+    public static int BlocksDeleted;
+    public static int DeadCodeEliminated;
+    public static int ResolveCPEAttempts;
+    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 HIRInstructions;
+    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 RedundantConditionals;
+    public static int FrameStatesCreated;
+    public static int FrameStateValuesCreated;
+
+    public static void print() {
+        printClassFields(C1XMetrics.class);
+
+    }
+
+    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/Compiler/src/com/sun/c1x/C1XOptions.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,212 @@
+/*
+ * 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.sun.c1x;
+
+import com.sun.c1x.debug.TTY.*;
+
+/**
+ * This class encapsulates options that control the behavior of the C1X 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.
+ *
+ * @author Ben L. Titzer
+ */
+public final class C1XOptions {
+
+    // Checkstyle: stop
+    private static final boolean ____ = false;
+    // Checkstyle: resume
+
+    // inlining settings
+    public static boolean OptInline                          = ____;
+    public static boolean OptInlineExcept                    = ____;
+    public static boolean OptInlineSynchronized              = ____;
+
+    public static int     MaximumInstructionCount            = 37000;
+    public static float   MaximumInlineRatio                 = 0.90f;
+    public static int     MaximumInlineSize                  = 35;
+    public static int     MaximumTrivialSize                 = 6;
+    public static int     MaximumInlineLevel                 = 9;
+    public static int     MaximumRecursiveInlineLevel        = 1;
+    public static int     MaximumDesiredSize                 = 8000;
+    public static int     MaximumShortLoopSize               = 5;
+
+    // intrinsification settings
+    public static boolean OptIntrinsify                      = ____;
+
+    // debugging settings
+    public static boolean VerifyPointerMaps                  = ____;
+    public static boolean PinAllInstructions                 = ____;
+    public static boolean TestPatching                       = ____;
+    public static boolean FatalUnimplemented                 = ____;
+    public static int     MethodEndBreakpointGuards          = 0;
+    public static boolean ZapStackOnMethodEntry              = ____;
+    public static boolean StressLinearScan                   = ____;
+
+    /**
+     * See {@link Filter#Filter(String, Object)}.
+     */
+    public static String  PrintFilter                        = null;
+
+    // printing settings
+    public static boolean PrintHIR                           = ____;
+    public static boolean PrintInliningFailures              = ____;
+    public static boolean PrintLIR                           = ____;
+    public static boolean PrintCFGToFile                     = ____;
+    public static boolean PrintMetrics                       = ____;
+    public static boolean PrintTimers                        = ____;
+    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 boolean TraceRelocation                    = ____;
+    public static boolean TraceLIRVisit                      = ____;
+    public static boolean TraceAssembler                     = ____;
+    public static int     TraceBytecodeParserLevel           = 0;
+    public static boolean PrintAssumptions                   = ____;
+    public static boolean PrintInlinedIntrinsics             = ____;
+
+    // IR checking
+    public static boolean InterpretInvokedMethods            = ____;
+    public static boolean PrintStateInInterpreter            = ____;
+
+    // canonicalizer settings
+    public static boolean CanonicalizeIntrinsics             = true;
+    public static boolean CanonicalizeFloatingPoint          = true;
+    public static boolean CanonicalizeNarrowingInStores      = true;
+    public static boolean CanonicalizeConstantFields         = true;
+    public static boolean CanonicalizeUnsafes                = true;
+    public static boolean CanonicalizeMultipliesToShifts     = true;
+    public static boolean CanonicalizeObjectCheckCast        = true;
+    public static boolean CanonicalizeObjectInstanceOf       = true;
+    public static boolean CanonicalizeFoldableMethods        = true;
+    public static boolean CanonicalizeArrayStoreChecks       = true;
+
+    // all optimization settings
+    public static boolean OptCanonicalize;
+    public static boolean OptLocalValueNumbering;
+    public static boolean OptLocalLoadElimination;
+    public static boolean OptCSEArrayLength;
+    public static boolean OptGlobalValueNumbering;
+    public static boolean OptCEElimination;
+    public static boolean OptBlockMerging;
+    public static boolean OptBlockSkipping;
+    public static boolean OptNullCheckElimination;
+    public static boolean OptIterativeNCE;
+    public static boolean OptFlowSensitiveNCE;
+    public static boolean OptDeadCodeElimination1;
+    public static boolean OptDeadCodeElimination2;
+    public static boolean OptControlFlow;
+    public static boolean OptMoveElimination;
+
+    // optimistic optimization settings
+    public static boolean UseAssumptions                = true;
+
+    // state merging settings
+    public static boolean AssumeVerifiedBytecode        = ____;
+    public static boolean PhiSimplify                   = true;
+    public static boolean PhiLoopStores                 = true;
+
+    // miscellaneous settings
+    public static boolean SupportObjectConstants        = true;
+
+    // Linear scan settings
+    public static boolean CopyPointerStackArguments     = true;
+
+    // Code generator settings
+    public static boolean GenLIR                        = true;
+    public static boolean GenCode                       = true;
+
+    public static boolean UseConstDirectCall            = false;
+
+    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 int     InitialCodeBufferSize         = 232;
+    public static boolean DetailedAsserts               = true;
+
+    // Runtime settings
+    public static int     ReadPrefetchInstr             = 0;
+    public static boolean UseStackMapTableLiveness      = ____;
+    public static int     StackShadowPages              = 2;
+
+    // Assembler settings
+    public static boolean CommentedAssembly             = ____;
+    public static boolean PrintLIRWithAssembly          = ____;
+    public static int     Atomics                       = 0;
+    public static boolean UseNormalNop                  = true;
+    public static boolean UseAddressNop                 = true;
+    public static boolean UseIncDec                     = ____;
+    public static boolean UseXmmLoadAndClearUpper       = ____;
+    public static boolean UseXmmRegToRegMoveAll         = ____;
+
+    static {
+        setOptimizationLevel(1);
+    }
+
+    public static void setOptimizationLevel(int level) {
+        final boolean l = (level >= 1);
+        final boolean ll = (level >= 2);
+        final boolean lll = (level >= 3);
+
+        // Level 1 optimizations
+        OptCanonicalize                 = l;
+        OptLocalValueNumbering          = l;
+        OptLocalLoadElimination         = l;
+        PhiLoopStores                   = l;
+        OptControlFlow                  = l;
+        OptMoveElimination              = l;
+        OptNullCheckElimination         = l;
+
+        // Level 2 optimizations
+        OptInline                       = ll;
+        OptBlockMerging                 = ll;
+
+        // Level 3 optimizations
+        OptCSEArrayLength               = lll;
+        OptIntrinsify                   = lll;
+        OptInlineExcept                 = lll;
+        OptInlineSynchronized           = lll;
+        UseStackMapTableLiveness        = lll;
+        UseAssumptions                  = lll;
+        OptIterativeNCE                 = lll;
+        OptFlowSensitiveNCE             = lll;
+        OptDeadCodeElimination1         = lll;
+        OptDeadCodeElimination2         = lll;
+        OptGlobalValueNumbering         = lll;
+        OptCEElimination                = lll;
+        OptBlockSkipping                = lll;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/C1XTimers.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,82 @@
+/*
+ * 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.sun.c1x;
+
+import com.sun.c1x.debug.*;
+
+/**
+ * This class contains timers that record the amount of time spent in various
+ * parts of the compiler.
+ *
+ * @author Christian Wimmer
+ */
+public enum C1XTimers {
+    HIR_CREATE("Create HIR"),
+    HIR_OPTIMIZE("Optimize HIR"),
+    NCE("Nullcheck elimination"),
+    LIR_CREATE("Create LIR"),
+    LIFETIME_ANALYSIS("Lifetime Analysis"),
+    LINEAR_SCAN("Linear Scan"),
+    RESOLUTION("Resolution"),
+    DEBUG_INFO("Create Debug Info"),
+    CODE_CREATE("Create Code");
+
+    private final String name;
+    private long start;
+    private long total;
+
+    private C1XTimers(String name) {
+        this.name = name;
+    }
+
+    public void start() {
+        start = System.nanoTime();
+    }
+
+    public void stop() {
+        total += System.nanoTime() - start;
+    }
+
+    public static void reset() {
+        for (C1XTimers t : values()) {
+            t.total = 0;
+        }
+    }
+
+    public static void print() {
+        long total = 0;
+        for (C1XTimers timer : C1XTimers.values()) {
+            total += timer.total;
+        }
+        if (total == 0) {
+            return;
+        }
+
+        TTY.println();
+        for (C1XTimers timer : C1XTimers.values()) {
+            TTY.println("%-20s: %7.4f s (%5.2f%%)", timer.name, timer.total / 1000000000.0, timer.total * 100.0 / total);
+            timer.total = 0;
+        }
+        TTY.println();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/alloc/ControlFlowOptimizer.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,283 @@
+/*
+ * 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.sun.c1x.alloc;
+
+import java.util.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.graph.*;
+import com.sun.c1x.ir.*;
+import com.sun.c1x.lir.*;
+import com.sun.c1x.util.*;
+import com.sun.cri.ci.*;
+
+/**
+ * This class performs basic optimizations on the control flow graph after LIR generation.
+ *
+ * @author Thomas Wuerthinger
+ */
+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<BlockBegin> code = ir.linearScanOrder();
+
+        // push the OSR entry block to the end so that we're not jumping over it.
+        BlockBegin osrEntry = ((Base) code.get(0).end()).osrEntry();
+        if (osrEntry != null) {
+            int index = osrEntry.linearScanNumber();
+            assert code.get(index) == osrEntry : "wrong index";
+            code.remove(index);
+            code.add(osrEntry);
+        }
+
+        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<BlockBegin> code, BlockBegin headerBlock, int headerIdx) {
+        int i = headerIdx + 1;
+        int maxEnd = Math.min(headerIdx + C1XOptions.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;
+            BlockBegin 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);
+
+                // correct the flags so that any loop alignment occurs in the right place.
+                assert code.get(endIdx).checkBlockFlag(BlockBegin.BlockFlag.BackwardBranchTarget) : "must be backward branch target";
+                code.get(endIdx).clearBlockFlag(BlockBegin.BlockFlag.BackwardBranchTarget);
+                code.get(headerIdx).setBlockFlag(BlockBegin.BlockFlag.BackwardBranchTarget);
+            }
+        }
+    }
+
+    private void reorderShortLoops(List<BlockBegin> code) {
+        for (int i = code.size() - 1; i >= 0; i--) {
+            BlockBegin block = code.get(i);
+
+            if (block.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader)) {
+                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(BlockBegin block) {
+        if (block.numberOfSux() != 1 ||
+            block.numberOfExceptionHandlers() != 0 ||
+            block == ir.startBlock ||
+            block.isExceptionEntry() ||
+            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";
+        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";
+
+        // block must have exactly one successor
+
+        return instructions.size() == 2 && instructions.get(instructions.size() - 1).info == null;
+    }
+
+    private void deleteEmptyBlocks(List<BlockBegin> code) {
+        int oldPos = 0;
+        int newPos = 0;
+        int numBlocks = code.size();
+
+        while (oldPos < numBlocks) {
+            BlockBegin block = code.get(oldPos);
+
+            if (canDeleteBlock(block)) {
+                BlockBegin newTarget = block.suxAt(0);
+
+                // propagate backward branch target flag for correct code alignment
+                if (block.checkBlockFlag(BlockBegin.BlockFlag.BackwardBranchTarget)) {
+                    newTarget.setBlockFlag(BlockBegin.BlockFlag.BackwardBranchTarget);
+                }
+
+                // update the block references in any branching LIR instructions
+                for (BlockBegin pred : block.predecessors()) {
+                    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);
+                        }
+                    }
+                }
+
+                // adjust successor and predecessor lists
+                ir.replaceBlock(block, newTarget);
+                C1XMetrics.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++;
+        }
+        Util.truncate(code, newPos);
+
+        assert verify(code);
+    }
+
+    private void deleteUnnecessaryJumps(List<BlockBegin> code) {
+        // skip the last block because there a branch is always necessary
+        for (int i = code.size() - 2; i >= 0; i--) {
+            BlockBegin 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;
+
+                assert lastBranch.block() != null : "last branch must always have a block as target";
+                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<BlockBegin> code) {
+        for (int i = code.size() - 1; i >= 0; i--) {
+            BlockBegin 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--) {
+                    BlockBegin 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<BlockBegin> code) {
+        for (BlockBegin block : code) {
+            List<LIRInstruction> instructions = block.lir().instructionsList();
+
+            for (LIRInstruction instr : instructions) {
+                if (instr instanceof LIRBranch) {
+                    LIRBranch opBranch = (LIRBranch) instr;
+                    assert opBranch.block() == null || code.contains(opBranch.block()) : "missing successor branch from: " + block + " to: " + opBranch.block();
+                    assert opBranch.unorderedBlock() == null || code.contains(opBranch.unorderedBlock()) : "missing successor branch from: " + block + " to: " + opBranch.unorderedBlock();
+                }
+            }
+
+            for (BlockBegin sux : block.end().successors()) {
+                assert code.contains(sux) : "missing successor from: " + block + "to: " + sux;
+            }
+
+            for (BlockBegin pred : block.predecessors()) {
+                assert code.contains(pred) : "missing predecessor from: " + block + "to: " + pred;
+            }
+        }
+
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/alloc/EdgeMoveOptimizer.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,298 @@
+/*
+ * 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.sun.c1x.alloc;
+
+import java.util.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.ir.*;
+import com.sun.c1x.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<BlockBegin> 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--) {
+            BlockBegin block = blockList.get(i);
+
+            if (block.numberOfPreds() > 1 && !block.checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry)) {
+                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(BlockBegin 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";
+        assert !block.checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry) : "exception handlers not allowed";
+
+        // setup a list with the LIR instructions of all predecessors
+        for (int i = 0; i < numPreds; i++) {
+            BlockBegin pred = block.predAt(i);
+            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;
+            }
+
+            assert pred.suxAt(0) == block : "invalid control flow";
+            assert predInstructions.get(predInstructions.size() - 1).code == LIROpcode.Branch : "block with successor must end with branch";
+            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(BlockBegin block) {
+
+        edgeInstructionSeqences.clear();
+        int numSux = block.numberOfSux();
+
+        List<LIRInstruction> instructions = block.lir().instructionsList();
+
+        assert numSux == 2 : "method should not be called otherwise";
+        assert instructions.get(instructions.size() - 1).code == LIROpcode.Branch : "block with successor must end with branch";
+        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 (C1XOptions.DetailedAsserts) {
+            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");
+                }
+            }
+        }
+
+        // setup a list with the lir-instructions of all successors
+        for (int i = 0; i < numSux; i++) {
+            BlockBegin 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";
+            assert !sux.checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry) : "exception handlers not allowed";
+
+            // 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/Compiler/src/com/sun/c1x/alloc/Interval.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.alloc;
+
+import java.util.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.debug.*;
+import com.sun.c1x.lir.*;
+import com.sun.c1x.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) {
+        C1XMetrics.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 (C1XOptions.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 (C1XOptions.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/Compiler/src/com/sun/c1x/alloc/IntervalWalker.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.alloc;
+
+import com.sun.c1x.*;
+import com.sun.c1x.alloc.Interval.*;
+import com.sun.c1x.debug.*;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class IntervalWalker {
+
+    protected final C1XCompilation 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 (C1XOptions.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 (C1XOptions.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/Compiler/src/com/sun/c1x/alloc/LIRInsertionBuffer.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.alloc;
+
+import java.util.*;
+
+import com.sun.c1x.lir.*;
+import com.sun.c1x.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/Compiler/src/com/sun/c1x/alloc/LinearScan.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,2559 @@
+/*
+ * 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.sun.c1x.alloc;
+
+import static com.sun.cri.ci.CiUtil.*;
+import static java.lang.reflect.Modifier.*;
+
+import java.util.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.alloc.Interval.*;
+import com.sun.c1x.debug.*;
+import com.sun.c1x.gen.*;
+import com.sun.c1x.graph.*;
+import com.sun.c1x.ir.*;
+import com.sun.c1x.ir.BlockBegin.BlockFlag;
+import com.sun.c1x.lir.*;
+import com.sun.c1x.lir.LIRInstruction.OperandMode;
+import com.sun.c1x.observer.*;
+import com.sun.c1x.util.*;
+import com.sun.c1x.value.*;
+import com.sun.c1x.value.FrameState.PhiProcedure;
+import com.sun.c1x.value.FrameState.ValueProcedure;
+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 C1XCompilation 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 BlockBegin[] 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
+     * BlockBegin block} containing the instruction. Entries should be retrieved with
+     * {@link #blockForId(int)} as the id is not simply an index into this array.
+     */
+    BlockBegin[] opIdToBlockMap;
+
+    /**
+     * Bit set for each variable that is contained in each loop.
+     */
+    BitMap2D intervalInLoop;
+
+    public LinearScan(C1XCompilation 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 BlockBegin[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;
+    }
+
+    BlockBegin 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}
+     */
+    BlockBegin 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 (C1XOptions.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 (C1XOptions.DetailedAsserts) {
+            checkIntervals(interval);
+        }
+
+        LIRInsertionBuffer insertionBuffer = new LIRInsertionBuffer();
+        int numBlocks = blockCount();
+        for (int i = 0; i < numBlocks; i++) {
+            BlockBegin 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 (C1XOptions.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 (C1XOptions.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 (C1XOptions.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 BlockBegin[numInstructions];
+
+        int opId = 0;
+        int index = 0;
+
+        for (int i = 0; i < numBlocks; i++) {
+            BlockBegin 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.id = 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++) {
+            BlockBegin block = blockAt(i);
+            final CiBitMap liveGen = new CiBitMap(liveSize);
+            final CiBitMap liveKill = new CiBitMap(liveSize);
+
+            if (block.isExceptionEntry()) {
+                // Phi functions at the begin of an exception handler are
+                // implicitly defined (= killed) at the beginning of the block.
+                block.stateBefore().forEachLivePhi(block, new PhiProcedure() {
+                    public boolean doPhi(Phi phi) {
+                        liveKill.set(operandNumber(phi.operand()));
+                        return true;
+                    }
+                });
+            }
+
+            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 (C1XOptions.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 (C1XOptions.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) {
+                    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 (C1XOptions.TraceLinearScanLevel >= 4) {
+                                        TTY.println("  Setting liveGen for value %s, LIR opId %d, operand %d", Util.valueString(value), op.id, operandNum);
+                                    }
+                                }
+                            } 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 (C1XOptions.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 (C1XOptions.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
+
+            LIRBlock lirBlock = block.lirBlock();
+            lirBlock.liveGen = liveGen;
+            lirBlock.liveKill = liveKill;
+            lirBlock.liveIn = new CiBitMap(liveSize);
+            lirBlock.liveOut = new CiBitMap(liveSize);
+
+            if (C1XOptions.TraceLinearScanLevel >= 4) {
+                TTY.println("liveGen  B%d %s", block.blockID, block.lirBlock.liveGen);
+                TTY.println("liveKill B%d %s", block.blockID, block.lirBlock.liveKill);
+            }
+        } // end of block iteration
+
+        intervalInLoop = localIntervalInLoop;
+    }
+
+    private void verifyTemp(CiBitMap 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(BlockBegin block, CiBitMap 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;
+        CiBitMap liveOut = new CiBitMap(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)
+        // Exception handlers must be processed because not all live values are
+        // present in the state array, e.g. because of global value numbering
+        do {
+            changeOccurred = false;
+
+            // iterate all blocks in reverse order
+            for (int i = numBlocks - 1; i >= 0; i--) {
+                BlockBegin block = blockAt(i);
+                LIRBlock lirBlock = block.lirBlock();
+
+                changeOccurredInBlock = false;
+
+                // liveOut(block) is the union of liveIn(sux), for successors sux of block
+                int n = block.numberOfSux();
+                int e = block.numberOfExceptionHandlers();
+                if (n + e > 0) {
+                    // block has successors
+                    if (n > 0) {
+                        liveOut.setFrom(block.suxAt(0).lirBlock.liveIn);
+                        for (int j = 1; j < n; j++) {
+                            liveOut.setUnion(block.suxAt(j).lirBlock.liveIn);
+                        }
+                    } else {
+                        liveOut.clearAll();
+                    }
+                    for (int j = 0; j < e; j++) {
+                        liveOut.setUnion(block.exceptionHandlerAt(j).lirBlock.liveIn);
+                    }
+
+                    if (!lirBlock.liveOut.isSame(liveOut)) {
+                        // A change occurred. Swap the old and new live out sets to avoid copying.
+                        CiBitMap temp = lirBlock.liveOut;
+                        lirBlock.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!
+                    CiBitMap liveIn = lirBlock.liveIn;
+                    liveIn.setFrom(lirBlock.liveOut);
+                    liveIn.setDifference(lirBlock.liveKill);
+                    liveIn.setUnion(lirBlock.liveGen);
+                }
+
+                if (C1XOptions.TraceLinearScanLevel >= 4) {
+                    traceLiveness(changeOccurredInBlock, iterationCount, block);
+                }
+            }
+            iterationCount++;
+
+            if (changeOccurred && iterationCount > 50) {
+                throw new CiBailout("too many iterations in computeGlobalLiveSets");
+            }
+        } while (changeOccurred);
+
+        if (C1XOptions.DetailedAsserts) {
+            verifyLiveness(numBlocks);
+        }
+
+        // check that the liveIn set of the first block is empty
+        CiBitMap liveInArgs = new CiBitMap(ir.startBlock.lirBlock.liveIn.size());
+        if (!ir.startBlock.lirBlock.liveIn.isSame(liveInArgs)) {
+            if (C1XOptions.DetailedAsserts) {
+                reportFailure(numBlocks);
+            }
+
+            // 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("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.lirBlock.liveIn.toString());
+
+        // print some additional information to simplify debugging
+        for (int operandNum = 0; operandNum < ir.startBlock.lirBlock.liveIn.size(); operandNum++) {
+            if (ir.startBlock.lirBlock.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());
+
+                for (int j = 0; j < numBlocks; j++) {
+                    BlockBegin block = blockAt(j);
+                    if (block.lirBlock.liveGen.get(operandNum)) {
+                        TTY.println("  used in block B%d", block.blockID);
+                    }
+                    if (block.lirBlock.liveKill.get(operandNum)) {
+                        TTY.println("  defined in block B%d", block.blockID);
+                    }
+                }
+            }
+        }
+    }
+
+    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++) {
+            BlockBegin block = blockAt(i);
+            for (int j = 0; j <= operands.maxRegisterNumber(); j++) {
+                assert !block.lirBlock.liveIn.get(j) : "liveIn  set of fixed register must be empty";
+                assert !block.lirBlock.liveOut.get(j) : "liveOut set of fixed register must be empty";
+                assert !block.lirBlock.liveGen.get(j) : "liveGen set of fixed register must be empty";
+            }
+        }
+    }
+
+    private void traceLiveness(boolean changeOccurredInBlock, int iterationCount, BlockBegin block) {
+        char c = iterationCount == 0 || changeOccurredInBlock ? '*' : ' ';
+        TTY.print("(%d) liveIn%c  B%d ", iterationCount, c, block.blockID);
+        TTY.println(block.lirBlock.liveIn.toString());
+        TTY.print("(%d) liveOut%c B%d ", iterationCount, c, block.blockID);
+        TTY.println(block.lirBlock.liveOut.toString());
+    }
+
+    Interval addUse(CiValue operand, int from, int to, RegisterPriority registerPriority, CiKind kind) {
+        if (!isProcessed(operand)) {
+            return null;
+        }
+        if (C1XOptions.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 (C1XOptions.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 (C1XOptions.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 (C1XOptions.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;
+
+            } else if (move.operand().isVariableOrRegister() && move.result().isVariableOrRegister()) {
+                // Move from register to register
+                if (blockForId(op.id).checkBlockFlag(BlockBegin.BlockFlag.OsrEntry)) {
+                    // special handling of phi-function moves inside osr-entry blocks
+                    // input operand must have a register instead of output operand (leads to better register
+                    // allocation)
+                    return RegisterPriority.ShouldHaveRegister;
+                }
+            }
+        }
+
+        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()) {
+                // Move from register to register
+                if (blockForId(op.id).checkBlockFlag(BlockBegin.BlockFlag.OsrEntry)) {
+                    // special handling of phi-function moves inside osr-entry blocks
+                    // input operand must have a register instead of output operand (leads to better register
+                    // allocation)
+                    return RegisterPriority.MustHaveRegister;
+                }
+
+                // 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 (C1XOptions.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 (C1XOptions.TraceLinearScanLevel >= 4) {
+                        TTY.println("found move from stack slot %s to %s", slot, move.result());
+                    }
+                }
+
+                Interval interval = intervalFor(move.result());
+                CiStackSlot copySlot = slot;
+                if (C1XOptions.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 (C1XOptions.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 (C1XOptions.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--) {
+            BlockBegin 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;
+            CiBitMap live = block.lirBlock.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 (C1XOptions.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.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopEnd) && 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 (C1XOptions.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 (C1XOptions.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
+
+            // (tw) Make sure that no spill store optimization is applied for phi instructions that flow into exception handlers.
+            if (block.isExceptionEntry()) {
+                FrameState stateBefore = block.stateBefore();
+                stateBefore.forEachLivePhi(block, new PhiProcedure() {
+                    @Override
+                    public boolean doPhi(Phi phi) {
+                        Interval interval = intervalFor(phi.operand());
+                        if (interval != null) {
+                            interval.setSpillState(SpillState.NoOptimization);
+                        }
+                        return true;
+                    }
+                });
+            }
+
+        } // 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 (C1XOptions.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 (C1XOptions.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(BlockBegin 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(BlockBegin 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(BlockBegin fromBlock, BlockBegin toBlock, MoveResolver moveResolver) {
+        assert moveResolver.checkEmpty();
+
+        int numOperands = operands.size();
+        CiBitMap liveAtEdge = toBlock.lirBlock.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.lirBlock.liveOut.get(operandNum) && toBlock.lirBlock.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(BlockBegin fromBlock, BlockBegin toBlock, MoveResolver moveResolver) {
+        if (fromBlock.numberOfSux() <= 1) {
+            if (C1XOptions.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 (C1XOptions.TraceLinearScanLevel >= 4) {
+                TTY.println("inserting moves at beginning of toBlock B%d", toBlock.blockID);
+            }
+
+            if (C1XOptions.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);
+        CiBitMap blockCompleted = new CiBitMap(numBlocks);
+        CiBitMap alreadyResolved = new CiBitMap(numBlocks);
+
+        int i;
+        for (i = 0; i < numBlocks; i++) {
+            BlockBegin block = blockAt(i);
+
+            // check if block has only one predecessor and only one successor
+            if (block.numberOfPreds() == 1 && block.numberOfSux() == 1 && block.numberOfExceptionHandlers() == 0 && !block.isExceptionEntry()) {
+                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";
+                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) {
+                    BlockBegin pred = block.predAt(0);
+                    BlockBegin sux = block.suxAt(0);
+
+                    // prevent optimization of two consecutive blocks
+                    if (!blockCompleted.get(pred.linearScanNumber()) && !blockCompleted.get(sux.linearScanNumber())) {
+                        if (C1XOptions.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)) {
+                BlockBegin fromBlock = blockAt(i);
+                alreadyResolved.setFrom(blockCompleted);
+
+                int numSux = fromBlock.numberOfSux();
+                for (int s = 0; s < numSux; s++) {
+                    BlockBegin toBlock = fromBlock.suxAt(s);
+
+                    // check for duplicate edges between the same blocks (can happen with switch blocks)
+                    if (!alreadyResolved.get(toBlock.linearScanNumber())) {
+                        if (C1XOptions.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();
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    void resolveExceptionEntry(BlockBegin block, CiValue operand, MoveResolver moveResolver) {
+        if (intervalFor(operand) == null) {
+            // if a phi function is never used, no interval is created . ignore this
+            return;
+        }
+
+        Interval interval = intervalAtBlockBegin(block, operand);
+        CiValue location = interval.location();
+
+        if (location.isRegister() && interval.alwaysInMemory()) {
+            // the interval is split to get a short range that is located on the stack
+            // in the following two cases:
+            // * the interval started in memory (e.g. method parameter), but is currently in a register
+            // this is an optimization for exception handling that reduces the number of moves that
+            // are necessary for resolving the states when an exception uses this exception handler
+            // * the interval would be on the fpu stack at the begin of the exception handler
+            // this is not allowed because of the complicated fpu stack handling on Intel
+
+            // range that will be spilled to memory
+            int fromOpId = block.firstLirInstructionId();
+            int toOpId = fromOpId + 1; // short live range of length 1
+            assert interval.from() <= fromOpId && interval.to() >= toOpId : "no split allowed between exception entry and first instruction";
+
+            if (interval.from() != fromOpId) {
+                // the part before fromOpId is unchanged
+                interval = interval.split(fromOpId, this);
+                interval.assignLocation(location);
+            }
+            assert interval.from() == fromOpId : "must be true now";
+
+            Interval spilledPart = interval;
+            if (interval.to() != toOpId) {
+                // the part after toOpId is unchanged
+                spilledPart = interval.splitFromStart(toOpId, this);
+                moveResolver.addMapping(spilledPart, interval);
+            }
+            assignSpillSlot(spilledPart);
+
+            assert spilledPart.from() == fromOpId && spilledPart.to() == toOpId : "just checking";
+        }
+    }
+
+    void resolveExceptionEntry(final BlockBegin block, final MoveResolver moveResolver) {
+        assert block.checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry) : "should not call otherwise";
+        assert moveResolver.checkEmpty();
+
+        // visit all registers where the liveIn bit is set
+        for (int operandNum = block.lirBlock.liveIn.nextSetBit(0); operandNum >= 0; operandNum = block.lirBlock.liveIn.nextSetBit(operandNum + 1)) {
+            resolveExceptionEntry(block, operands.operandFor(operandNum), moveResolver);
+        }
+
+        // the liveIn bits are not set for phi functions of the xhandler entry, so iterate them separately
+        block.stateBefore().forEachLivePhi(block, new PhiProcedure() {
+            public boolean doPhi(Phi phi) {
+                resolveExceptionEntry(block, phi.operand(), moveResolver);
+                return true;
+            }
+        });
+
+        if (moveResolver.hasMappings()) {
+            // insert moves after first instruction
+            moveResolver.setInsertPosition(block.lir(), 0);
+            moveResolver.resolveAndAppendMoves();
+        }
+    }
+
+    void resolveExceptionEdge(ExceptionHandler handler, int throwingOpId, CiValue operand, Phi phi, MoveResolver moveResolver) {
+        if (intervalFor(operand) == null) {
+            // if a phi function is never used, no interval is created . ignore this
+            return;
+        }
+
+        // the computation of toInterval is equal to resolveCollectMappings,
+        // but fromInterval is more complicated because of phi functions
+        BlockBegin toBlock = handler.entryBlock();
+        Interval toInterval = intervalAtBlockBegin(toBlock, operand);
+
+        if (phi != null) {
+            // phi function of the exception entry block
+            // no moves are created for this phi function in the LIRGenerator, so the
+            // interval at the throwing instruction must be searched using the operands
+            // of the phi function
+            Value fromValue = phi.inputAt(handler.phiOperand());
+            Constant con = null;
+            if (fromValue instanceof Constant) {
+                con = (Constant) fromValue;
+            }
+            if (con != null && (con.operand().isIllegal() || con.operand().isConstant())) {
+                // unpinned constants may have no register, so add mapping from constant to interval
+                moveResolver.addMapping(con.asConstant(), toInterval);
+            } else {
+                // search split child at the throwing opId
+                Interval fromInterval = intervalAtOpId(fromValue.operand(), throwingOpId);
+                if (fromInterval != toInterval) {
+                    moveResolver.addMapping(fromInterval, toInterval);
+                    // with phi functions it can happen that the same fromValue is used in
+                    // multiple mappings, so notify move-resolver that this is allowed
+                    moveResolver.setMultipleReadsAllowed();
+                }
+            }
+        } else {
+            // no phi function, so use regNum also for fromInterval
+            // search split child at the throwing opId
+            Interval fromInterval = intervalAtOpId(operand, throwingOpId);
+            if (fromInterval != toInterval) {
+                // optimization to reduce number of moves: when toInterval is on stack and
+                // the stack slot is known to be always correct, then no move is necessary
+                if (!fromInterval.alwaysInMemory() || fromInterval.spillSlot() != toInterval.location()) {
+                    moveResolver.addMapping(fromInterval, toInterval);
+                }
+            }
+        }
+    }
+
+    void resolveExceptionEdge(final ExceptionHandler handler, final int throwingOpId, final MoveResolver moveResolver) {
+        if (C1XOptions.TraceLinearScanLevel >= 4) {
+            TTY.println("resolving exception handler B%d: throwingOpId=%d", handler.entryBlock().blockID, throwingOpId);
+        }
+
+        assert moveResolver.checkEmpty();
+        assert handler.lirOpId() == -1 : "already processed this xhandler";
+        handler.setLirOpId(throwingOpId);
+        assert handler.entryCode() == null : "code already present";
+
+        // visit all registers where the liveIn bit is set
+        BlockBegin block = handler.entryBlock();
+        for (int operandNum = block.lirBlock.liveIn.nextSetBit(0); operandNum >= 0; operandNum = block.lirBlock.liveIn.nextSetBit(operandNum + 1)) {
+            resolveExceptionEdge(handler, throwingOpId, operands.operandFor(operandNum), null, moveResolver);
+        }
+
+        // the liveIn bits are not set for phi functions of the xhandler entry, so iterate them separately
+        block.stateBefore().forEachLivePhi(block, new PhiProcedure() {
+            public boolean doPhi(Phi phi) {
+                resolveExceptionEdge(handler, throwingOpId, phi.operand(), phi, moveResolver);
+                return true;
+            }
+        });
+
+        if (moveResolver.hasMappings()) {
+            LIRList entryCode = new LIRList(gen);
+            moveResolver.setInsertPosition(entryCode, 0);
+            moveResolver.resolveAndAppendMoves();
+
+            entryCode.jump(handler.entryBlock());
+            handler.setEntryCode(entryCode);
+        }
+    }
+
+    void resolveExceptionHandlers() {
+        MoveResolver moveResolver = new MoveResolver(this);
+        //LIRVisitState visitor = new LIRVisitState();
+        int numBlocks = blockCount();
+
+        int i;
+        for (i = 0; i < numBlocks; i++) {
+            BlockBegin block = blockAt(i);
+            if (block.checkBlockFlag(BlockFlag.ExceptionEntry)) {
+                resolveExceptionEntry(block, moveResolver);
+            }
+        }
+
+        for (i = 0; i < numBlocks; i++) {
+            BlockBegin block = blockAt(i);
+            LIRList ops = block.lir();
+            int numOps = ops.length();
+
+            // iterate all instructions of the block. skip the first because it is always a label
+            assert !ops.at(0).hasOperands() : "first operation must always be a label";
+            for (int j = 1; j < numOps; j++) {
+                LIRInstruction op = ops.at(j);
+                int opId = op.id;
+
+                if (opId != -1 && op.info != null) {
+                    // visit operation to collect all operands
+                    for (ExceptionHandler handler : op.exceptionEdges()) {
+                        resolveExceptionEdge(handler, opId, moveResolver);
+                    }
+
+                } else if (C1XOptions.DetailedAsserts) {
+                    assert op.exceptionEdges().size() == 0 : "missed exception handler";
+                }
+            }
+        }
+    }
+
+    // * 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 (C1XOptions.DetailedAsserts) {
+                BlockBegin 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.lirBlock.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, CiBitMap frameRefMap, CiBitMap regRefMap) {
+        if (C1XOptions.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, CiBitMap frameRefMap, CiBitMap 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);
+                }
+            }
+        }
+    }
+
+    CiValue toCiValue(int opId, Value value) {
+        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)";
+
+            if (con != null && !con.isLive() && !operand.isConstant()) {
+                // Unpinned constants may have a variable operand for a part of the lifetime
+                // or may be illegal when it was optimized away,
+                // so always use a constant operand
+                operand = con.asConstant();
+            }
+
+            if (operand.isVariable()) {
+                OperandMode mode = OperandMode.Input;
+                BlockBegin block = blockForId(opId);
+                if (block.numberOfSux() == 1 && opId == 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.lirBlock.liveOut.get(operandNumber(operand))) {
+                            opId = 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, opId, mode);
+                assert !hasCall(opId) || operand.isStackSlot() || !isCallerSave(operand) : "cannot have caller-save register operands at calls";
+                return operand;
+            } else if (operand.isRegister()) {
+                assert value instanceof LoadRegister;
+                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;
+        }
+    }
+
+    CiFrame computeFrameForState(int opId, FrameState state, CiBitMap frameRefMap) {
+        CiFrame callerFrame = null;
+
+        FrameState callerState = state.callerState();
+        if (callerState != null) {
+            // process recursively to compute outermost scope first
+            callerFrame = computeFrameForState(opId, callerState, frameRefMap);
+        }
+
+        CiValue[] values = new CiValue[state.valuesSize() + state.locksSize()];
+        int valueIndex = 0;
+
+        for (int i = 0; i < state.valuesSize(); i++) {
+            values[valueIndex++] = toCiValue(opId, state.valueAt(i));
+        }
+
+        for (int i = 0; i < state.locksSize(); i++) {
+            if (compilation.runtime.sizeOfBasicObjectLock() != 0) {
+                CiStackSlot monitorAddress = frameMap.toMonitorBaseStackAddress(i);
+                values[valueIndex++] = monitorAddress;
+                assert frameRefMap != null;
+                CiStackSlot objectAddress = frameMap.toMonitorObjectStackAddress(i);
+                LIRDebugInfo.setBit(frameRefMap, 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(opId, lock);
+                }
+            }
+        }
+
+        return new CiFrame(callerFrame, state.scope().method, state.bci, values, state.localsSize(), state.stackSize(), state.locksSize());
+    }
+
+    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;
+                CiBitMap frameRefMap = new CiBitMap(frameWords);
+                CiBitMap regRefMap = !op.hasCall ? new CiBitMap(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 (C1XOptions.DetailedAsserts) {
+                assert info.debugInfo.frame().equals(computeFrame(info.state, op.id, new CiBitMap(info.debugInfo.frameRefMap.size())));
+            }
+        }
+    }
+
+    CiFrame computeFrame(FrameState state, int opId, CiBitMap frameRefMap) {
+        if (C1XOptions.TraceLinearScanLevel >= 3) {
+            TTY.println("creating debug information at opId %d", opId);
+        }
+        return computeFrameForState(opId, state, frameRefMap);
+    }
+
+    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) {
+                // exception handling
+                if (compilation.hasExceptionHandlers()) {
+                    for (ExceptionHandler handler : op.exceptionEdges()) {
+                        if (handler.entryCode() != null) {
+                            assignLocations(handler.entryCode().instructionsList(), 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 (BlockBegin block : sortedBlocks) {
+            assignLocations(block.lir().instructionsList(), iw);
+        }
+    }
+
+    public void allocate() {
+        if (C1XOptions.PrintTimers) {
+            C1XTimers.LIFETIME_ANALYSIS.start();
+        }
+
+        numberInstructions();
+
+        printLir("Before register allocation", true);
+
+        computeLocalLiveSets();
+        computeGlobalLiveSets();
+
+        buildIntervals();
+        sortIntervalsBeforeAllocation();
+
+        if (C1XOptions.PrintTimers) {
+            C1XTimers.LIFETIME_ANALYSIS.stop();
+            C1XTimers.LINEAR_SCAN.start();
+        }
+
+        printIntervals("Before register allocation");
+
+        allocateRegisters();
+
+        if (C1XOptions.PrintTimers) {
+            C1XTimers.LINEAR_SCAN.stop();
+            C1XTimers.RESOLUTION.start();
+        }
+
+        resolveDataFlow();
+        if (compilation.hasExceptionHandlers()) {
+            resolveExceptionHandlers();
+        }
+
+        if (C1XOptions.PrintTimers) {
+            C1XTimers.RESOLUTION.stop();
+            C1XTimers.DEBUG_INFO.start();
+        }
+
+        C1XMetrics.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 (C1XOptions.DetailedAsserts) {
+            verify();
+        }
+
+        eliminateSpillMoves();
+        assignLocations();
+
+        if (C1XOptions.DetailedAsserts) {
+            verifyIntervals();
+        }
+
+        if (C1XOptions.PrintTimers) {
+            C1XTimers.DEBUG_INFO.stop();
+            C1XTimers.CODE_CREATE.start();
+        }
+
+        printLir("After register number assignment", true);
+
+        EdgeMoveOptimizer.optimize(ir.linearScanOrder());
+        if (C1XOptions.OptControlFlow) {
+            ControlFlowOptimizer.optimize(ir);
+        }
+
+        printLir("After control flow optimization", false);
+    }
+
+    void printIntervals(String label) {
+        if (C1XOptions.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++) {
+                BlockBegin 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 (C1XOptions.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.hir().startBlock, hirValid, true));
+        }
+    }
+
+    boolean verify() {
+        // (check that all intervals have a correct register and that no registers are overwritten)
+        if (C1XOptions.TraceLinearScanLevel >= 2) {
+            TTY.println(" verifying intervals *");
+        }
+        verifyIntervals();
+
+        if (C1XOptions.TraceLinearScanLevel >= 2) {
+            TTY.println(" verifying that no oops are in fixed intervals *");
+        }
+        //verifyNoOopsInFixedIntervals();
+
+        if (C1XOptions.TraceLinearScanLevel >= 2) {
+            TTY.println(" verifying that unpinned constants are not alive across block boundaries");
+        }
+        verifyConstants();
+
+        if (C1XOptions.TraceLinearScanLevel >= 2) {
+            TTY.println(" verifying register allocation *");
+        }
+        verifyRegisters();
+
+        if (C1XOptions.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 (C1XOptions.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++) {
+            BlockBegin 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++) {
+            BlockBegin block = blockAt(i);
+            CiBitMap liveAtEdge = block.lirBlock.liveIn;
+
+            // visit all operands where the liveAtEdge bit is set
+            for (int operandNum = liveAtEdge.nextSetBit(0); operandNum >= 0; operandNum = liveAtEdge.nextSetBit(operandNum + 1)) {
+                if (C1XOptions.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/Compiler/src/com/sun/c1x/alloc/LinearScanWalker.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,984 @@
+/*
+ * 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.sun.c1x.alloc;
+
+import static com.sun.cri.ci.CiUtil.*;
+
+import java.util.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.alloc.Interval.RegisterBinding;
+import com.sun.c1x.alloc.Interval.RegisterPriority;
+import com.sun.c1x.alloc.Interval.SpillState;
+import com.sun.c1x.alloc.Interval.State;
+import com.sun.c1x.debug.*;
+import com.sun.c1x.ir.*;
+import com.sun.c1x.lir.*;
+import com.sun.c1x.util.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ci.CiRegister.RegisterFlag;
+
+/**
+ *
+ * @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();
+    }
+
+    BlockBegin blockAt(int idx) {
+        return allocator.blockAt(idx);
+    }
+
+    BlockBegin 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;
+        BlockBegin 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(BlockBegin minBlock, BlockBegin 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--) {
+            BlockBegin 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 (C1XOptions.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
+            BlockBegin 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)
+            BlockBegin 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 (C1XOptions.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 (C1XOptions.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 (C1XOptions.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 (C1XOptions.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)
+                            BlockBegin loopBlock = allocator.blockForId(loopEndPos);
+
+                            if (C1XOptions.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 (C1XOptions.TraceLinearScanLevel >= 4) {
+                                    TTY.println("      loop optimization not necessary");
+                                }
+                            } else {
+                                if (C1XOptions.TraceLinearScanLevel >= 4) {
+                                    TTY.println("      loop optimization successful");
+                                }
+                            }
+                        }
+                    }
+
+                    if (optimalSplitPos == -1) {
+                        // not calculated by loop optimization
+                        optimalSplitPos = findOptimalSplitPos(minBlock, maxBlock, maxSplitPos);
+                    }
+                }
+            }
+        }
+        if (C1XOptions.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 (C1XOptions.TraceLinearScanLevel >= 2) {
+            TTY.println("----- splitting interval: ");
+        }
+        if (C1XOptions.TraceLinearScanLevel >= 4) {
+            TTY.println(interval.logString(allocator));
+        }
+        if (C1XOptions.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 (C1XOptions.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 (C1XOptions.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 (C1XOptions.TraceLinearScanLevel >= 2) {
+            TTY.println("      split interval in two parts (insertMoveWhenActivated: %b)", moveNecessary);
+        }
+        if (C1XOptions.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 (C1XOptions.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 (C1XOptions.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 (C1XOptions.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 (C1XOptions.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 (C1XOptions.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 (C1XOptions.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 (C1XOptions.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 (C1XOptions.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 (C1XOptions.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 (C1XOptions.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 (C1XOptions.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 (C1XOptions.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 (C1XOptions.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 (C1XOptions.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 (C1XOptions.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 (C1XOptions.TraceLinearScanLevel >= 2) {
+            TTY.println("+++++ activating interval " + interval.logString(allocator));
+        }
+
+        if (C1XOptions.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 (C1XOptions.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 (C1XOptions.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 (C1XOptions.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 (C1XOptions.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/Compiler/src/com/sun/c1x/alloc/MoveResolver.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,367 @@
+/*
+ * 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.sun.c1x.alloc;
+
+import java.util.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.debug.*;
+import com.sun.c1x.lir.*;
+import com.sun.c1x.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 (C1XOptions.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 (C1XOptions.TraceLinearScanLevel >= 4) {
+            TTY.print("MoveResolver: inserted move from constant %s to %d (%s)", fromOpr, toInterval.operandNumber, toInterval.location());
+        }
+    }
+
+    private void resolveMappings() {
+        //if (C1XOptions.TraceLinearScanLevel >= 4) TTY.println("MoveResolver: resolving mappings for Block B%d, index %d", insertList.block() != null ? insertList.block().blockID : -1, insertIdx);
+        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 (C1XOptions.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) {
+        //if (C1XOptions.TraceLinearScanLevel >= 4) TTY.println("MoveResolver: setting insert position to Block B%d, index %d", insertList.block() != null ? insertList.block().blockID : -1, 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 (C1XOptions.TraceLinearScanLevel >= 4) TTY.println("MoveResolver: moving insert position to Block B%d, index %d", (insertList != null && insertList.block() != null) ? insertList.block().blockID : -1, 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 (C1XOptions.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 (C1XOptions.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/Compiler/src/com/sun/c1x/alloc/OperandPool.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,268 @@
+/*
+ * 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.sun.c1x.alloc;
+
+import java.util.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.ir.*;
+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 C1XOptions#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 CiBitMap mustBeByteRegister;
+
+    /**
+     * Records which variable operands have the {@link VariableFlag#MustStartInMemory} flag set.
+     */
+    private CiBitMap mustStartInMemory;
+
+    /**
+     * Records which variable operands have the {@link VariableFlag#MustStayInMemory} flag set.
+     */
+    private CiBitMap 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 CiBitMap set(CiBitMap map, CiVariable variable) {
+        if (map == null) {
+            int length = CiBitMap.roundUpLength(variable.index + 1);
+            map = new CiBitMap(length);
+        } else if (map.size() <= variable.index) {
+            int length = CiBitMap.roundUpLength(variable.index + 1);
+            map.grow(length);
+        }
+        map.set(variable.index);
+        return map;
+    }
+
+    private static boolean get(CiBitMap 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 = C1XOptions.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/Compiler/src/com/sun/c1x/alloc/Range.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.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/Compiler/src/com/sun/c1x/alloc/RegisterVerifier.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,299 @@
+/*
+ * 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.sun.c1x.alloc;
+
+import java.util.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.debug.*;
+import com.sun.c1x.ir.*;
+import com.sun.c1x.lir.*;
+import com.sun.c1x.util.*;
+import com.sun.cri.ci.*;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+final class RegisterVerifier {
+
+    LinearScan allocator;
+    List<BlockBegin> workList; // all blocks that must be processed
+    ArrayMap<Interval[]> savedStates; // saved information of previous check
+
+    // simplified access to methods of LinearScan
+    C1XCompilation 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(BlockBegin block) {
+        return savedStates.get(block.blockID);
+    }
+
+    void setStateForBlock(BlockBegin block, Interval[] savedState) {
+        savedStates.put(block.blockID, savedState);
+    }
+
+    void addToWorkList(BlockBegin block) {
+        if (!workList.contains(block)) {
+            workList.add(block);
+        }
+    }
+
+    RegisterVerifier(LinearScan allocator) {
+        this.allocator = allocator;
+        workList = new ArrayList<BlockBegin>(16);
+        this.savedStates = new ArrayMap<Interval[]>();
+
+    }
+
+    void verify(BlockBegin 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 {
+            BlockBegin block = workList.get(0);
+            workList.remove(0);
+
+            processBlock(block);
+        } while (!workList.isEmpty());
+    }
+
+    void processBlock(BlockBegin block) {
+        if (C1XOptions.TraceLinearScanLevel >= 2) {
+            TTY.println();
+            TTY.println("processBlock B%d", block.blockID);
+        }
+
+        // must copy state because it is modified
+        Interval[] inputState = copy(stateForBlock(block));
+
+        if (C1XOptions.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 (BlockBegin succ : block.end().successors()) {
+            processSuccessor(succ, inputState);
+        }
+    }
+
+    void processXhandler(ExceptionHandler xhandler, Interval[] inputState) {
+        if (C1XOptions.TraceLinearScanLevel >= 2) {
+            TTY.println("processXhandler B%d", xhandler.entryBlock().blockID);
+        }
+
+        // must copy state because it is modified
+        inputState = copy(inputState);
+
+        if (xhandler.entryCode() != null) {
+            processOperations(xhandler.entryCode(), inputState);
+        }
+        processSuccessor(xhandler.entryBlock(), inputState);
+    }
+
+    void processSuccessor(BlockBegin 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 (C1XOptions.TraceLinearScanLevel >= 4) {
+                            TTY.println("processSuccessor B%d: invalidating slot %d", block.blockID, i);
+                        }
+                    }
+                }
+            }
+
+            if (savedStateCorrect) {
+                // already processed block with correct inputState
+                if (C1XOptions.TraceLinearScanLevel >= 2) {
+                    TTY.println("processSuccessor B%d: previous visit already correct", block.blockID);
+                }
+            } else {
+                // must re-visit this block
+                if (C1XOptions.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 (C1XOptions.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 (C1XOptions.TraceLinearScanLevel >= 4) {
+                    TTY.println("        %s = %s", reg, interval.operand);
+                }
+            } else if (inputState[regNum] != null) {
+                if (C1XOptions.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 (C1XOptions.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);
+                }
+            }
+
+            // process xhandler before output and temp operands
+            List<ExceptionHandler> xhandlers = op.exceptionEdges();
+            n = xhandlers.size();
+            for (int k = 0; k < n; k++) {
+                processXhandler(xhandlers.get(k), inputState);
+            }
+
+            // 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/Compiler/src/com/sun/c1x/asm/AbstractAssembler.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,230 @@
+/*
+ * 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.sun.c1x.asm;
+
+import java.util.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.debug.*;
+import com.sun.c1x.ir.*;
+import com.sun.c1x.lir.*;
+import com.sun.c1x.util.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ci.CiTargetMethod.CodeComment;
+import com.sun.cri.ci.CiTargetMethod.Mark;
+import com.sun.cri.ri.*;
+
+/**
+ * @author Marcelo Cintra
+ * @author Thomas Wuerthinger
+ */
+public abstract class AbstractAssembler {
+
+    public final Buffer codeBuffer;
+    public final CiTarget target;
+    public final CiTargetMethod targetMethod;
+    public List<ExceptionInfo> exceptionInfoList;
+
+    public AbstractAssembler(CiTarget target) {
+        this.target = target;
+        this.targetMethod = new CiTargetMethod();
+        this.codeBuffer = new Buffer(target.arch.byteOrder);
+    }
+
+    public final void bind(Label l) {
+        assert !l.isBound() : "can bind label only once";
+        l.bind(codeBuffer.position());
+        l.patchInstructions(this);
+    }
+
+    public void setFrameSize(int frameSize) {
+        targetMethod.setFrameSize(frameSize);
+    }
+
+    public CiTargetMethod finishTargetMethod(Object name, RiRuntime runtime, int registerRestoreEpilogueOffset, boolean isStub) {
+        // Install code, data and frame size
+        targetMethod.setTargetCode(codeBuffer.close(false), codeBuffer.position());
+        targetMethod.setRegisterRestoreEpilogueOffset(registerRestoreEpilogueOffset);
+
+        // Record exception handlers if they exist
+        if (exceptionInfoList != null) {
+            for (ExceptionInfo ei : exceptionInfoList) {
+                int codeOffset = ei.codeOffset;
+                for (ExceptionHandler handler : ei.exceptionHandlers) {
+                    int entryOffset = handler.entryCodeOffset();
+                    RiType caughtType = handler.handler.catchType();
+                    targetMethod.recordExceptionHandler(codeOffset, ei.bci, handler.scopeCount(), entryOffset, handler.handlerBCI(), caughtType);
+                }
+            }
+        }
+
+        if (C1XOptions.PrintMetrics) {
+            C1XMetrics.TargetMethods++;
+            C1XMetrics.CodeBytesEmitted += targetMethod.targetCodeSize();
+            C1XMetrics.SafepointsEmitted += targetMethod.safepoints.size();
+            C1XMetrics.DirectCallSitesEmitted += targetMethod.directCalls.size();
+            C1XMetrics.IndirectCallSitesEmitted += targetMethod.indirectCalls.size();
+            C1XMetrics.DataPatches += targetMethod.dataReferences.size();
+            C1XMetrics.ExceptionHandlersEmitted += targetMethod.exceptionHandlers.size();
+        }
+
+        if (C1XOptions.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: " + target.arch.registerReferenceMapBitCount);
+
+            if (C1XOptions.PrintCodeBytes) {
+                Util.printSection("Code", Util.SUB_SECTION_CHARACTER);
+                TTY.println("Code: %d bytes", targetMethod.targetCodeSize());
+                Util.printBytes(0L, targetMethod.targetCode(), 0, targetMethod.targetCodeSize(), C1XOptions.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.exceptionHandlers != null) {
+                if (exceptionInfoList == null) {
+                    exceptionInfoList = new ArrayList<ExceptionInfo>(4);
+                }
+                exceptionInfoList.add(new ExceptionInfo(pcOffset, info.exceptionHandlers, info.state.bci));
+            }
+        }
+    }
+
+    public void recordImplicitException(int pcOffset, LIRDebugInfo info) {
+        // record an implicit exception point
+        if (info != null) {
+            targetMethod.recordSafepoint(pcOffset, info.debugInfo());
+            recordExceptionHandlers(pcOffset, info);
+        }
+    }
+
+    protected void recordDirectCall(int posBefore, int posAfter, Object target, LIRDebugInfo info) {
+        CiDebugInfo debugInfo = info != null ? info.debugInfo() : null;
+        targetMethod.recordCall(posBefore, target, debugInfo, true);
+    }
+
+    protected void recordIndirectCall(int posBefore, int posAfter, Object target, LIRDebugInfo info) {
+        CiDebugInfo debugInfo = info != null ? info.debugInfo() : null;
+        targetMethod.recordCall(posBefore, target, debugInfo, false);
+    }
+
+    public void recordSafepoint(int pos, LIRDebugInfo info) {
+        // safepoints always need debug info
+        CiDebugInfo debugInfo = info.debugInfo();
+        targetMethod.recordSafepoint(pos, debugInfo);
+    }
+
+    public CiAddress recordDataReferenceInCode(CiConstant data) {
+        assert data != null;
+
+        int pos = codeBuffer.position();
+
+        if (C1XOptions.TraceRelocation) {
+            TTY.print("Data reference in code: pos = %d, data = %s", pos, data.toString());
+        }
+
+        targetMethod.recordDataReference(pos, data);
+        return CiAddress.Placeholder;
+    }
+
+    public Mark recordMark(Object id, Mark[] references) {
+        return targetMethod.recordMark(codeBuffer.position(), id, references);
+    }
+
+    public abstract void nop();
+
+    public abstract void nullCheck(CiRegister r);
+
+    public abstract void align(int codeEntryAlignment);
+
+    public abstract void patchJumpTarget(int branch, int target);
+
+    public final void emitByte(int x) {
+        codeBuffer.emitByte(x);
+    }
+
+    public final void emitShort(int x) {
+        codeBuffer.emitShort(x);
+    }
+
+    public final void emitInt(int x) {
+        codeBuffer.emitInt(x);
+    }
+
+    public final void emitLong(long x) {
+        codeBuffer.emitLong(x);
+    }
+
+    public void blockComment(String s) {
+        targetMethod.addAnnotation(new CodeComment(codeBuffer.position(), s));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/asm/Buffer.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,251 @@
+/*
+ * 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.sun.c1x.asm;
+
+import java.util.*;
+
+import com.sun.c1x.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.CiArchitecture.ByteOrder;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public final class Buffer {
+
+    private byte[] data;
+    private int position;
+    private int mark = -1;
+
+    private final ByteOrder byteOrder;
+
+    public Buffer(ByteOrder byteOrder) {
+        this.byteOrder = byteOrder;
+        this.data = new byte[C1XOptions.InitialCodeBufferSize];
+    }
+
+    public void reset() {
+        position = 0;
+        mark = -1;
+    }
+
+    /**
+     * Closes this buffer. No extra data can be written to this buffer after this call.
+     *
+     * @param trimmedCopy if {@code true}, then a copy of the underlying byte array up to (but not including)
+     *            {@code position()} is returned
+     * @return the data in this buffer or a trimmed copy if {@code trimmedCopy} is {@code true}
+     */
+    public byte[] close(boolean trimmedCopy) {
+        byte[] result = trimmedCopy ? Arrays.copyOf(data, position()) : data;
+        data = null;
+        return result;
+    }
+
+    public int emitBytes(byte[] arr, int off, int len) {
+        assert data != null : "must not use buffer after calling finished!";
+        int oldPos = position;
+        ensureSize(position + len);
+        System.arraycopy(arr, off, data, position, len);
+        position += len;
+        return oldPos;
+    }
+
+    public int emitByte(int b) {
+        int oldPos = position;
+        position = emitByte(b, oldPos);
+        return oldPos;
+    }
+
+    public int emitShort(int b) {
+        int oldPos = position;
+        position = emitShort(b, oldPos);
+        return oldPos;
+    }
+
+    public int emitInt(int b) {
+        int oldPos = position;
+        position = emitInt(b, oldPos);
+        return oldPos;
+    }
+
+    public int emitLong(long b) {
+        int oldPos = position;
+        position = emitLong(b, oldPos);
+        return oldPos;
+    }
+
+    private boolean isByte(int b) {
+        return b == (b & 0xFF);
+    }
+
+    private boolean isShort(int s) {
+        return s == (s & 0xFFFF);
+    }
+
+    /**
+     * Places a bookmark at the {@linkplain #position() current position}.
+     *
+     * @return the previously placed bookmark or {@code -1} if there was no bookmark
+     */
+    public int mark() {
+        int mark = this.mark;
+        this.mark = position;
+        return mark;
+    }
+
+    private void ensureSize(int length) {
+        if (length >= data.length) {
+            data = Arrays.copyOf(data, data.length * 4);
+            C1XMetrics.CodeBufferCopies++;
+        }
+    }
+
+    public int emitByte(int b, int pos) {
+        assert data != null : "must not use buffer after calling finished!";
+        assert isByte(b);
+        ensureSize(pos + 1);
+        data[pos++] = (byte) b;
+        return pos;
+    }
+
+    public int emitShort(int b, int pos) {
+        assert data != null : "must not use buffer after calling finished!";
+        assert isShort(b);
+        ensureSize(pos + 2);
+        if (byteOrder == ByteOrder.BigEndian) {
+            data[pos++] = (byte) ((b >> 8) & 0xFF);
+            data[pos++] = (byte) (b & 0xFF);
+
+        } else {
+            assert byteOrder == ByteOrder.LittleEndian;
+            data[pos++] = (byte) (b & 0xFF);
+            data[pos++] = (byte) ((b >> 8) & 0xFF);
+        }
+        return pos;
+    }
+
+    public int emitInt(int b, int pos) {
+        assert data != null : "must not use buffer after calling finished!";
+        ensureSize(pos + 4);
+        if (byteOrder == ByteOrder.BigEndian) {
+            data[pos++] = (byte) ((b >> 24) & 0xFF);
+            data[pos++] = (byte) ((b >> 16) & 0xFF);
+            data[pos++] = (byte) ((b >> 8) & 0xFF);
+            data[pos++] = (byte) (b & 0xFF);
+        } else {
+            assert byteOrder == ByteOrder.LittleEndian;
+            data[pos++] = (byte) (b & 0xFF);
+            data[pos++] = (byte) ((b >> 8) & 0xFF);
+            data[pos++] = (byte) ((b >> 16) & 0xFF);
+            data[pos++] = (byte) ((b >> 24) & 0xFF);
+        }
+        return pos;
+    }
+
+    public int emitLong(long b, int pos) {
+        assert data != null : "must not use buffer after calling finished!";
+        ensureSize(pos + 8);
+
+        if (byteOrder == ByteOrder.BigEndian) {
+            data[pos++] = (byte) ((b >> 56) & 0xFF);
+            data[pos++] = (byte) ((b >> 48) & 0xFF);
+            data[pos++] = (byte) ((b >> 40) & 0xFF);
+            data[pos++] = (byte) ((b >> 32) & 0xFF);
+            data[pos++] = (byte) ((b >> 24) & 0xFF);
+            data[pos++] = (byte) ((b >> 16) & 0xFF);
+            data[pos++] = (byte) ((b >> 8) & 0xFF);
+            data[pos++] = (byte) (b & 0xFF);
+        } else {
+            assert byteOrder == ByteOrder.LittleEndian;
+            data[pos++] = (byte) (b & 0xFF);
+            data[pos++] = (byte) ((b >> 8) & 0xFF);
+            data[pos++] = (byte) ((b >> 16) & 0xFF);
+            data[pos++] = (byte) ((b >> 24) & 0xFF);
+            data[pos++] = (byte) ((b >> 32) & 0xFF);
+            data[pos++] = (byte) ((b >> 40) & 0xFF);
+            data[pos++] = (byte) ((b >> 48) & 0xFF);
+            data[pos++] = (byte) ((b >> 56) & 0xFF);
+        }
+        return pos;
+    }
+
+    public int position() {
+        return position;
+    }
+
+    public void setPosition(int position) {
+        assert position >= 0 && position <= data.length;
+        this.position = position;
+    }
+
+    public int getByte(int pos) {
+        return Bytes.beU1(data, pos);
+    }
+
+    public int getShort(int pos) {
+        if (byteOrder == ByteOrder.BigEndian) {
+            return
+                (data[pos + 0] & 0xff) << 8 |
+                (data[pos + 1] & 0xff) << 0;
+        } else {
+            assert byteOrder == ByteOrder.LittleEndian;
+            return
+                (data[pos + 1] & 0xff) << 8  |
+                (data[pos + 0] & 0xff) << 0;
+        }
+    }
+
+    public int getInt(int pos) {
+        if (byteOrder == ByteOrder.BigEndian) {
+            return
+                (data[pos + 0] & 0xff) << 24 |
+                (data[pos + 1] & 0xff) << 16 |
+                (data[pos + 2] & 0xff) << 8  |
+                (data[pos + 3] & 0xff) << 0;
+        } else {
+            assert byteOrder == ByteOrder.LittleEndian;
+            return
+                (data[pos + 3] & 0xff) << 24 |
+                (data[pos + 2] & 0xff) << 16 |
+                (data[pos + 1] & 0xff) << 8  |
+                (data[pos + 0] & 0xff) << 0;
+        }
+    }
+
+    public byte[] copyData(int start, int end) {
+        return Arrays.copyOfRange(data, start, end);
+    }
+
+    /**
+     * Copies the data from this buffer into a given array.
+     *
+     * @param dst the destination array
+     * @param off starting position in {@code dst}
+     * @param len number of bytes to copy
+     */
+    public void copyInto(byte[] dst, int off, int len) {
+        System.arraycopy(data, 0, dst, off, len);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/asm/ExceptionInfo.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,44 @@
+/*
+ * 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.sun.c1x.asm;
+
+import java.util.*;
+
+import com.sun.c1x.ir.*;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class ExceptionInfo {
+
+    public final int codeOffset;
+    public final List<ExceptionHandler> exceptionHandlers;
+    public final int bci;
+
+    public ExceptionInfo(int pcOffset, List<ExceptionHandler> exceptionHandlers, int bci) {
+        this.codeOffset = pcOffset;
+        this.exceptionHandlers = exceptionHandlers;
+        this.bci = bci;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/asm/Label.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.asm;
+
+import com.sun.c1x.util.*;
+
+/**
+ * This class represents a label within assembly code.
+ *
+ * @author Marcelo Cintra
+ */
+public final class Label {
+
+    private int position = -1;
+
+    /**
+     * References to instructions that jump to this unresolved label.
+     * These instructions need to be patched when the label is bound
+     * using the {@link #patchInstructions(AbstractAssembler)} method.
+     */
+    private IntList patchPositions = new IntList(4);
+
+    /**
+     * Returns the position of this label in the code buffer.
+     * @return the position
+     */
+    public int position() {
+        assert position >= 0 : "Unbound label is being referenced";
+        return position;
+    }
+
+    public Label() {
+    }
+
+    public Label(int position) {
+        bind(position);
+    }
+
+    /**
+     * Binds the label to the specified position.
+     * @param pos the position
+     */
+    public void bind(int pos) {
+        this.position = pos;
+        assert isBound();
+    }
+
+    public boolean isBound() {
+        return position >= 0;
+    }
+
+    public void addPatchAt(int branchLocation) {
+        assert !isBound() : "Label is already bound";
+        patchPositions.add(branchLocation);
+    }
+
+    public void patchInstructions(AbstractAssembler masm) {
+        assert isBound() : "Label should be bound";
+        int target = position;
+        for (int i = 0; i < patchPositions.size(); ++i) {
+            int pos = patchPositions.get(i);
+            masm.patchJumpTarget(pos, target);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "label";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/debug/BlockPrinter.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,126 @@
+/*
+ * 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.sun.c1x.debug;
+
+import com.sun.c1x.graph.*;
+import com.sun.c1x.ir.*;
+import com.sun.c1x.util.*;
+import com.sun.c1x.value.*;
+
+/**
+ * Prints a listing for a {@linkplain BlockBegin block}.
+ *
+ * @author Doug Simon
+ */
+public class BlockPrinter implements BlockClosure {
+
+    private final InstructionPrinter ip;
+    private final boolean cfgOnly;
+    private final boolean liveOnly;
+
+    public BlockPrinter(IR ir, InstructionPrinter ip, boolean cfgOnly, boolean liveOnly) {
+        this.ip = ip;
+        this.cfgOnly = cfgOnly;
+        this.liveOnly = liveOnly;
+    }
+
+    public void apply(BlockBegin block) {
+        if (cfgOnly) {
+            ip.printInstruction(block);
+            ip.out().println();
+        } else {
+            printBlock(block, liveOnly);
+        }
+    }
+
+    public void printBlock(BlockBegin block, boolean liveOnly) {
+        ip.printInstruction(block);
+        LogStream out = ip.out();
+        out.println();
+        printFrameState(block.stateBefore(), out);
+        out.println();
+
+        out.println("inlining depth " + block.stateBefore().scope().level);
+
+        ip.printInstructionListingHeader();
+
+        for (Instruction i = block.next(); i != null; i = i.next()) {
+            if (!liveOnly || i.isLive()) {
+                ip.printInstructionListing(i);
+            }
+        }
+        out.println();
+
+    }
+
+    private static void printFrameState(FrameState newFrameState, LogStream out) {
+        int startPosition = out.position();
+        if (newFrameState.stackEmpty()) {
+          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/Compiler/src/com/sun/c1x/debug/CFGPrinter.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,673 @@
+/*
+ * 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.sun.c1x.debug;
+
+import java.io.*;
+import java.util.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.alloc.*;
+import com.sun.c1x.alloc.Interval.*;
+import com.sun.c1x.graph.*;
+import com.sun.c1x.ir.*;
+import com.sun.c1x.lir.*;
+import com.sun.c1x.lir.LIRInstruction.*;
+import com.sun.c1x.util.*;
+import com.sun.c1x.value.*;
+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 C1X 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>.
+ *
+ * @author Doug Simon
+ */
+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(BlockBegin block, List<BlockBegin> successors, Iterable<BlockBegin> handlers, boolean printHIR, boolean printLIR) {
+        begin("block");
+
+        out.print("name \"B").print(block.blockID).println('"');
+        out.print("from_bci ").println(block.bci());
+        out.print("to_bci ").println(block.end() == null ? -1 : block.end().bci());
+
+        out.print("predecessors ");
+        for (BlockBegin pred : block.predecessors()) {
+            out.print("\"B").print(pred.blockID).print("\" ");
+        }
+        out.println();
+
+        out.print("successors ");
+        for (BlockBegin succ : successors) {
+            out.print("\"B").print(succ.blockID).print("\" ");
+        }
+        out.println();
+
+        out.print("xhandlers");
+        for (BlockBegin handler : handlers) {
+            out.print("\"B").print(handler.blockID).print("\" ");
+        }
+        out.println();
+
+        out.print("flags ");
+        if (block.isStandardEntry()) {
+            out.print("\"std\" ");
+        }
+        if (block.isOsrEntry()) {
+            out.print("\"osr\" ");
+        }
+        if (block.isExceptionEntry()) {
+            out.print("\"ex\" ");
+        }
+        if (block.isSubroutineEntry()) {
+            out.print("\"sr\" ");
+        }
+        if (block.isBackwardBranchTarget()) {
+            out.print("\"bb\" ");
+        }
+        if (block.isParserLoopHeader()) {
+            out.print("\"plh\" ");
+        }
+        if (block.isCriticalEdgeSplit()) {
+            out.print("\"ces\" ");
+        }
+        if (block.isLinearScanLoopHeader()) {
+            out.print("\"llh\" ");
+        }
+        if (block.isLinearScanLoopEnd()) {
+            out.print("\"lle\" ");
+        }
+        out.println();
+
+        if (block.dominator() != null) {
+            out.print("dominator \"B").print(block.dominator().blockID).println('"');
+        }
+        if (block.loopIndex() != -1) {
+            out.print("loop_index ").println(block.loopIndex());
+            out.print("loop_depth ").println(block.loopDepth());
+        }
+
+        if (printHIR) {
+            printState(block);
+            printHIR(block);
+        }
+
+        if (printLIR) {
+            printLIR(block);
+        }
+
+        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(BlockBegin block) {
+        begin("states");
+
+        FrameState state = block.stateBefore();
+
+        do {
+            int stackSize = state.stackSize();
+            if (stackSize > 0) {
+                begin("stack");
+                out.print("size ").println(stackSize);
+                out.print("method \"").print(CiUtil.toLocation(state.scope().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(state.scope().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(state.scope().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++;
+                }
+            }
+            state = state.callerState();
+            end("locals");
+        } while (state != null);
+
+        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();
+
+        do {
+            buf.append(CiUtil.toLocation(state.scope().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");
+            state = state.callerState();
+        } while (state != null);
+        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:");
+            C1XCompilation compilation = C1XCompilation.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:");
+            CiBitMap 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(BlockBegin block) {
+        begin("IR");
+        out.println("HIR");
+        out.disableIndentation();
+        for (Instruction i = block.next(); i != null; i = i.next()) {
+            printInstructionHIR(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(BlockBegin 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(Instruction i) {
+        out.print("bci ").print(i.bci()).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);
+
+        String state = stateToString(i.stateBefore(), 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 (int bci = 0; bci < codeSize; ++bci) {
+            BlockBegin block = blockMap.get(bci);
+            if (block != null) {
+                printBlock(block, Arrays.asList(blockMap.getSuccessors(block)), blockMap.getHandlers(block), printHIR, printLIR);
+            }
+        }
+        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(BlockBegin startBlock, String label, final boolean printHIR, final boolean printLIR) {
+        begin("cfg");
+        out.print("name \"").print(label).println('"');
+        startBlock.iteratePreOrder(new BlockClosure() {
+            public void apply(BlockBegin block) {
+                List<BlockBegin> successors = block.end() != null ? block.end().successors() : new ArrayList<BlockBegin>(0);
+                printBlock(block, successors, block.exceptionHandlerBlocks(), 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/Compiler/src/com/sun/c1x/debug/CFGPrinterObserver.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,113 @@
+/*
+ * 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.c1x.debug;
+
+import java.io.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.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 C1XCompilation currentCompilation;
+    private CFGPrinter cfgPrinter;
+    private ByteArrayOutputStream buffer = null;
+
+    public CFGPrinterObserver() {
+    }
+
+    @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;
+        }
+
+        if (event.getStartBlock() != null) {
+            cfgPrinter.printCFG(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();
+
+        OutputStream cfgFileStream = CFGPrinter.cfgFileStream();
+        if (cfgFileStream != null) {
+            synchronized (cfgFileStream) {
+                try {
+                    cfgFileStream.write(buffer.toByteArray());
+                } catch (IOException e) {
+                    TTY.println("WARNING: Error writing CFGPrinter output for %s to disk: %s", event.getMethod(), e);
+                }
+            }
+        }
+
+        buffer.reset();
+        cfgPrinter = null;
+        currentCompilation = null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/debug/InstructionPrinter.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.debug;
+
+import static com.sun.c1x.debug.InstructionPrinter.InstructionLineColumn.*;
+
+import com.sun.c1x.ir.*;
+
+/**
+ * A {@link ValueVisitor} for {@linkplain #printInstruction(Value) printing}
+ * an {@link Instruction} 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.sun.c1x.util.Util#valueString(com.sun.c1x.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) {
+        if (instruction.isLive()) {
+            out.print('.');
+        }
+
+        int indentation = out.indentationLevel();
+        out.fillTo(BCI.position + indentation, ' ').
+             print(instruction instanceof Instruction ? ((Instruction) instruction).bci() : 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).stateBefore() + "]");
+        }
+        out.println();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/debug/LogStream.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,493 @@
+/*
+ * 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.sun.c1x.debug;
+
+import java.io.*;
+
+import com.sun.c1x.ir.*;
+import com.sun.c1x.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(format, args));
+        }
+        return this;
+    }
+
+    /**
+     * Writes an instruction formatted as a {@linkplain com.sun.c1x.util.Util#valueString(com.sun.c1x.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.sun.c1x.util.Util#valueString(com.sun.c1x.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/Compiler/src/com/sun/c1x/debug/TTY.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.debug;
+
+import java.io.*;
+import java.util.regex.*;
+
+import com.sun.c1x.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 C1X_TTY_LOG_FILE_PROPERTY = "c1x.tty.file";
+
+    private static final LogStream log;
+    static {
+        PrintStream out = System.out;
+        String value = System.getProperty(C1X_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/Compiler/src/com/sun/c1x/debug/package-info.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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 C1X development.
+ */
+package com.sun.c1x.debug;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/doc/IRInterpreter.txt	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,26 @@
+Current status and remaining issues in the IRInterpreter for HIR (September/18/09)
+=================================================================================
+
+Known Problems:
+With InterpretInvokedMethods disabled in C1XOptions:
+(2 fails)
+304: jtt/jvmni/JVM_GetClassContext01.java: (0) failed with false (expected true)
+557: jtt/reflect/Class_newInstance02.java: (0) failed with true (expected !java.lang.IllegalAccessException)
+
+The first problem is caused by the use of reflection in the IRInterpreter, and the calling stack is not as 
+expected by the JVM_GetClassContext01 test case. The second one is due to the private constructor of Class_newInstance01.
+Again, we are using reflection to call the newInstance() method to create an instance of class Class_newInstance01
+from the IRInterpreter class, which raises an IllegalAccessException.
+These are the only problems with all optimization levels.
+
+With InterpretInvokedMethods enabled in C1XOptions:
+(7 fails)
+245: jtt/except/Catch_StackOverflowError_03.java: (0) failed with !java.lang.InstantiationException (expected 0)
+304: jtt/jvmni/JVM_GetClassContext01.java: (0) failed with false (expected true)
+311: jtt/lang/Bridge_method01.java: (0) failed with unexpected com.sun.c1x.ci.CiBailout (expected 1)
+557: jtt/reflect/Class_newInstance02.java: (0) failed with true (expected !java.lang.IllegalAccessException)
+572: jtt/reflect/Invoke_virtual01.java: (1) failed with unexpected com.sun.c1x.ci.CiBailout (expected 55)
+575: jtt/reflect/Reflection_getCallerClass01.java: (1) failed with com.sun.c1x.debug.IRInterpreter$Evaluator (expected jtt.reflect.Reflection_getCallerClass01$Caller1)
+592: jtt/threads/Thread_isInterrupted04.java: (0) failed with false (expected true)
+
+Those are also due to reflection usage. The last problem has not been investigated.
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/doc/LoopPeeling.txt	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,43 @@
+Remaining Issues in the Loop Peeling optimization (September/18/09)
+===================================================================
+
+Known Problems:
+Currently loop peeling is not working when the loop has exception
+blocks. The algorithm has to be updated to handle these cases.
+
+Limitations:
+The algorithm performs loop peeling only on innermost loops. However,
+this is not a limitation. If one wants to peel the outermost loop(s),
+after peeling the innermost loop, an additional pass is necessary
+to update the blocks of the outermost loop, since after peeling
+the innermost loop, newer blocks are added to the CFG.
+
+Current status as of 09/18/2009
+After running using hir configuration, with optimization level 3, the
+following test cases produce wrong results:
+(4 fails)
+233: jtt/except/Catch_Loop01.java: (4) failed with unexpected com.sun.c1x.ci.CiBailout (expected -170)
+234: jtt/except/Catch_Loop02.java: (4) failed with unexpected com.sun.c1x.ci.CiBailout (expected -170)
+245: jtt/except/Catch_StackOverflowError_03.java: (0) failed with unexpected com.sun.c1x.ci.CiBailout (expected 0)
+272: jtt/hotpath/HP_array04.java: (80) failed with unexpected java.lang.AssertionError (expected 15645)
+
+All of them are related the known problem aforementioned.
+All the tests have the innermost loops peeled, and produce right results.
+
+Future Work:
+1- Add more loop tests to jtt. New tests should run the loop 0, 1, 2 or more iterations.
+
+2- Peel loops with exception blocks. 
+
+3- Currently, all innermost loops are peeled. Should we add logic to filter out some loops from loop peeling?
+
+4- Improve the way instructions are cloned. Now the algorithm visits the blocks in BFS order, which
+might produce errors depending on the order the blocks are visited.
+
+5- After inserting new phi instructions at exit blocks, we need to iterate over the remaining CFG to update instructions
+that may use the new phi. The way it's done now might me inefficient if the block has more than one exit node, since
+we can iterate over the same block more than once. This needs to be improved.
+
+5- For performance reasons, improve the way loops are represented, for example, to use a bitmap to represent the loop blocks.
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/doc/backend_open_issues.txt	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,22 @@
+Remaining Issues in the C1X backend (after the port July-Sep 09)
+======================================================================
+
+Maxine/Inspector Related Open Issues:
+   - Global stubs: Change calling convention (no longer write to callee stack as this makes stepping through the instructions for saving the parameters to global stubs impossible in the inspector)
+   - Reference maps: Corrently implement TargetMethod.prepareReferenceMap for C1XTargetMethod (checking for the need to stack walk a possible callee saved target method) and call it from Maxine
+   - Disassembler: The Maxine disassembler still does not correctly display every machine code instruction issued by C1X
+   - MaxRiRuntime and C1XTargetMethod have fixed dependencies on the X86 parts (instruction decoding, registers, calling convention), should be factored out
+
+Compile-Time Performance Improvements:
+   - Consider deleting the LIRItem class
+   - Make sure that LIROperand objects are not shared among LIR instructions and can therefore be directly modified by the LinearScan register allocator (no more need for the lazy creation of LIRAddress objects in the LIRInstruction class)
+   
+Run-Time Performance Improvements:
+   - Store mapping between machine code location and bytecode index in the target method (remove arguments from global stub calls), this decreases the number of necessary parameters especially for resolution instructions.
+   - Use Inline Cache on virtual method calls
+
+Better Portability:
+   - Integrate XIR; consider using CiLocation / CiConstant in XIR
+   - The JIT adapter frames should be a more general mechanism that receives two calling conventions (in form of an array of locations) and adapts between them automatically
+   - Have the possibility to register intrinsics by specifying XIR code
+   
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/doc/differences.txt	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,154 @@
+Differences between C1 and C1X, including upgrades and limitations
+(and some general information about C1)
+======================================================================
+
+StrictFP:
+   - C1X has removed the backend code to deal with the FPU stack, and therefore
+     requires SSE2 currently. StrictFP is still tracked in the front end.
+   - C1 will not inline methods with different strictfp-ness. C1X does not have this
+     limitation because it only targets SSE2 x86 processors.
+
+JSR/RET
+   - C1 will bail out if it encounters strange JSR/RET patterns
+       - recursive JSRs
+       - JSR regions that are shared with non-JSR code
+       - RET encountered out of JSR (would not verify)
+
+Exceptions
+   -  C1 will bailout if the code of an exception handler can be reached via normal
+      control flow.
+   => C1X might be extended to introduce a phi for the exception
+      object in this case.
+   -  C1 will bailout if an exception handler covers itself
+
+Verification
+   -  C1 does not rely on bytecode verification having been run. However, if it detects
+      type errors in its building the IR graph it will usually bail out.
+   -  C1 requires a bitmap of the bytecode, where a bit for
+      each byte of the bytecode indicates if the bytecode at that location starts a
+      basic block. It uses this to construct the basic block list in a single pass.
+   => Assertion failures and/or bugs in C1X that cause exceptions to be thrown bail out
+      the compilation instead of crashing the VM.
+   => C1X's BlockMap does not computes the basic block starts in one pass over the bytecode
+      and one pass over the successor lists.
+   => C1X computes the "stores in loops" only when loops are encountered in the CFG.
+      An option can select conservative mode (all locals stored in all loops) trades
+      faster parse speed for fewer optimization opportunities
+   => C1X includes an IRChecker that typechecks the entire IR and checks for CFG
+      consistency that can be run after each pass.
+
+Constants
+   => C1X allows unrestricted use of object constants throughout the code, including
+      folding reads of static final fields that reference objects.
+
+Pinning
+   => C1X pins fewer instructions than C1
+   ** C1X will eventually allow certain kinds of instructions to float outside the CFG
+      and be scheduled with a C2-lite scheduling pass.
+
+Synchronization
+   -  C1 will refuse to compile methods with unbalanced synchronization. This property is
+      computed by the bytecode verifier and supplied to C1.
+   ** C1X will not rely on the bytecode verifier to compute this but should do so itself.
+   => C1 relied on the backend to generate synchronization code for the root method's
+      synchronization operations. C1X inserts code into the start block and generates
+      and exception handler to do this explicitly.
+
+Optimizations
+   => C1X has many more options to turn on individual passes, parts of passes, approximations,
+      etc. It is designed to have three optimization levels:
+      0 = super-fast: essentially no optimization
+      1 = fast:       inlining, constant folding, and local optimizations
+      2 = optimized:  inlining, constant folding, local and global optimizations, including
+                      iterative versions of all algorithms
+   ** Planned optimizations for C1X that C1 does not have:
+      TypeCheckElimination:        remove redundant casts and devirtualize more call sites
+      ArrayBoundsCheckElimination: remove redundant array bounds checks and/or restructure
+                                   code to deoptimize when bounds checks within loops will fail
+      LoopPeeling:                 replicate the first iteration of a loop
+      LoopUnrolling:               replicate the body of certain shapes of loops
+      LoopInvariantCodeMotion:     move invariant code out of a loop
+      ProfileGuidedInlining:       use receiver method profiles to emit guarded inlines
+      ProfileGuidedBlockLayout:    use profiling information for code placement
+      Peephole:                    peephole optimize backend output
+
+Block Merging
+   ** C1X will replace branches to blocks with a single Goto with a branch to the
+      block's successor, if the blocks cannot be merged otherwise.
+
+Constant Folding / Strength reduction
+   -  C1 had some of its strength reduction logic built into the GraphBuilder because
+      the Canonicalizer could not return multiple instructions.
+   => C1X added this ability, moved the logic to Canonicalizer, and added a few new
+      strength reductions.
+   => C1X should have an interface for doing folding of @FOLD method calls
+   => C1X folds many intrinsic operations that don't have side effects
+   => C1X folds all the basic floating point operations
+   => C1X strength reduces (e >> C >> K) to (e >> (C + K)) when C and K are constant
+   => Multiplies of power-of-2 constants are reduced to shifts in the canonicalizer
+      (instead of the backend)
+   ** C1X will be able to run a global sparse conditional constant propagation phase
+      to catch any missed canonicalization opportunities after graph building.
+
+Switches
+   -  C1 did not detect back edges in tableswitch/lookupswitch default branches
+   => C1X does detect these back edges
+   => C1X moved the canonicalization code of 1 and 2 branch switches to canonicalizer,
+      where it belongs
+
+Inlining
+   -  C1 cannot inline:
+      -  native methods (or their stubs), except some intrinsics
+      -  methods whose class has not been initialized
+      -  methods with unbalanced monitors
+      -  methods with JSRs (this is probably technically possible now)
+
+   -  C1 will not inline:
+      -  methods with exception handlers (optional)
+      -  synchronized methods (optional)
+      -  if the maximum inline depth is reached (default = 9)
+      -  if the maximum recursive inline depth is reached (default = 1)
+      -  if the callee is larger than the maximum inline size (reduced to 90% at each level, starting at 35)
+      -  constructors for subclasses of Throwable
+      -  if the strictfp-ness of the callee is different than the caller (on x87)
+      -  abstract methods
+      -  synchronized intrinsics
+
+Load/store elimination
+   => C1X may eliminate loads of static fields, which C1 did not
+   => C1X distinguishes loads/stores to different fields in MemoryBuffer
+   => C1X assumes that RiField instances are unique when .isLoaded() is true
+
+Local/Global Value Numbering
+   => C1X improved local load elimination and no longer value numbers fields, reducing the
+      logic necessary in ValueMap, simplifying it and improving its performance.
+   => C1X reuses the same simplified ValueMap for GVN. Since heap accesses are no longer
+      value numbered, the logic to kill values is unnecessary, greatly simplifying
+      GVN.
+   ** A global version of load elimination will compensate for this loss in the future.
+   => C1X value numbers are always or'd with a high order bit when value numbering is possible
+      to prevent value numbering failing if the value number is accidentally 0.
+
+Nullcheck elimination
+   => A new flag, NonNull, indicates instructions that produce values that are guaranteed
+      to be non-null (e.g. NewXXX and Local 0, NullCheck). Instructions that require null
+      checks check this flag for their inputs in their constructors, eliminating most
+      redundant null checks immediately, without requiring the NullCheckEliminator to run.
+   => C1X uses a more efficient block ordering for null check elimination. The first pass is
+      optimistic and attempts to visit the blocks in reverse post-order. For acyclic graphs,
+      this almost always succeeds, requiring no iteration. Full iterative data flow analysis
+      can be enabled separately. Bitmaps used during the fixpoint calculation are much
+      smaller due to local numbering of instructions (as opposed to global IDs).
+   ** C1X will recognize If's that check against null and propagate the non-nullness across
+      the appropriate branches.
+
+BlockListBuilder
+   -  C1 had a vestigial loop map in BlockListBuilder which was not really used.
+   => C1X does not need to compute a complete loop map in order to do selective phi creation,
+      it builds the "storesInLoops" BitMap in BlockMap.
+
+Types
+   => C1X adds the declared type of method parameters to Local instructions, which
+      may help with devirtualization
+   => C1X makes local 0 of instance methods non-null at the start
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/doc/performance.txt	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,85 @@
+Issues that can be addressed for improving performance in C1X
+----------------------------------------------------------------
+
+- indicates not done
+* indicates done
+
+Backend:
+	- better handling of constants, especially immediates
+	- (non XIR) checkcast, instanceof: use nullity
+	- (non XIR) checkcast, instanceof: emit fastpath direct compare
+	- use LEA instruction on x86
+	- recognize pointer arithmetic addressing modes
+	- recognize multiply by 3, 5, 9 and emit lea rk, [rs, rs*2], etc
+	- Maxine XIR: make direct runtime calls instead of through global stub
+	- Maxine XIR: implement inline allocation
+	- Maxine XIR: implement biased locking fastpath
+	- Maxine XIR: faster subtype checks for classes, leaves
+	- Maxine XIR: make use of XirSite nullity, range check information
+	- better handling of tableswitch bytecode
+	- better handling of two operand LIR form
+	- Make the following bytecode implementations inline:
+		- f2i f2l f2d d2i d2l d2f (SSE2)
+		* lrem ldiv (64 bit)
+		- fneg dneg
+	- Make the following bytecode implementations global stubs:
+		- frem drem
+	- Global stubs: use EAX for return value as normal instead of [rsp - 16]
+    - Emit direct call to runtime for new instance, monitorenter, monitorexit
+
+	* XIR: expose nullity, range checkness across XIR interface
+	- XIR: make use of CSE'd array length
+	- XIR: generate special if-instanceof XIR variant with label parameters
+    - Optimize special cases of bytecodes:
+        - (MIN_INT / -1) in IDIV,IREM
+        - (MIN_LONG / -1) in LDIV,LREM
+        - (-infinity, Nan, +infinity) in F2I, F2L, D2I, D2L
+
+
+Frontend:
+    - Remove redundant null check branches in NullCheckEliminator
+	- XIR: implement HIR -> HIR xir translation
+	- Refactor exception edges to allow removal, optimization
+	- Implement typecast elimination
+	- Implement constant propagation
+	- Implement GVN of memory loads / stores
+	- Implement memory reordering
+	- Implement loop invariant code motion
+	- Optimize endianness conversions and endian-writes
+	      (e.g. (x >> 24 & 0xff) | (....)) and a[0] = x >> 24 ...
+	- Finish loop peeling
+	- Implement loop unrolling
+	- Allow value numbering of constant loads
+	- Finish loop peeling
+	- Guarded and multiple inlining
+	- Maxine: speculative leaf class and leaf method assumption
+	- Maxine: adjust static / dynamic inlining heuristics
+		  (e.g. static: trivial methods only in cold spots)
+    - Aggressive optimization of array copy
+
+Compilation speed:
+    - Make special iterators for LIROperand input, temp, output
+    - Add analysisInfo field to Value and use in NullCheckEliminator
+	- Remove RiConstantPool, cpi from unresolved HIR instructions (move to RiField, RiMethod)
+	- Use BlockList instead of ArrayList<Block> where appropriate
+	- Use FrameState instead of ValueStack
+	- Remove exceptionHandlers, make DebugInfo hold FrameState, CiCodePos,
+		exception flags and exception handlers
+	- Clean up and simplify LIRInstruction constructor
+	- Create fewer LIRAddresses
+	- Simplify LIRGenerator logic (forcing of loading, etc)
+	- LIROperand: split into virtual register table?
+	- Cleanup assembler and remove dead code, useless assertions
+	- Chain assembler byte buffers and only assemble at the end
+	- Pick optimal initial assembler byte buffer size
+	- Pick good initial sizes for LinearScan data structures
+	- Remove unnecessary uses of ArrayList and replace with arrays or other list
+	- Use iteration over ArrayList instead of explicit loop
+	- Revisit manual editing / removal of items from ArrayList
+	- Remove non-XIR backend
+	- Pre-assemble XIR for backend
+
+	* Initialize compilation-unique instruction id's lazily with thread local compilation
+	* Remove dead LIROpcodes
+	* Remove dead code in LIRGenerator, X86LIRGenerator, LIRAssembler, X86LIRAssembler
+		(remove commented out code)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/gen/LIRGenerator.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,2172 @@
+/*
+ * 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.sun.c1x.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.sun.c1x.*;
+import com.sun.c1x.alloc.*;
+import com.sun.c1x.alloc.OperandPool.VariableFlag;
+import com.sun.c1x.asm.*;
+import com.sun.c1x.debug.*;
+import com.sun.c1x.globalstub.*;
+import com.sun.c1x.graph.*;
+import com.sun.c1x.ir.*;
+import com.sun.c1x.ir.Value.Flag;
+import com.sun.c1x.lir.FrameMap.StackBlock;
+import com.sun.c1x.lir.*;
+import com.sun.c1x.opt.*;
+import com.sun.c1x.util.*;
+import com.sun.c1x.value.*;
+import com.sun.c1x.value.FrameState.PhiProcedure;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.bytecode.Bytecodes.MemoryBarriers;
+import com.sun.cri.ci.*;
+import com.sun.cri.ci.CiAddress.Scale;
+import com.sun.cri.ri.*;
+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.
+ *
+ * @author Thomas Wuerthinger
+ * @author Ben L. Titzer
+ * @author Marcelo Cintra
+ * @author Doug Simon
+ */
+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;
+    }
+
+    protected 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 BlockBegin sux;
+
+        SwitchRange(int lowKey, BlockBegin sux) {
+            this.lowKey = lowKey;
+            this.highKey = lowKey;
+            this.sux = sux;
+        }
+    }
+
+    protected final C1XCompilation compilation;
+    protected final IR ir;
+    protected final XirSupport xirSupport;
+    protected final RiXirGenerator xir;
+    protected final boolean isTwoOperand;
+
+    private BlockBegin 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;
+
+    public LIRGenerator(C1XCompilation 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);
+
+        // mark the liveness of all instructions if it hasn't already been done by the optimizer
+        LivenessMarker livenessMarker = new LivenessMarker(ir);
+        C1XMetrics.LiveHIRInstructions += livenessMarker.liveCount();
+    }
+
+    public ArrayList<DeoptimizationStub> deoptimizationStubs() {
+        return deoptimizationStubs;
+    }
+
+    public static class DeoptimizationStub {
+        public final Label label = new Label();
+        public final LIRDebugInfo info;
+
+        public DeoptimizationStub(FrameState state) {
+            info = new LIRDebugInfo(state, null);
+        }
+    }
+
+    public final void emitGuard(Guard x) {
+        FrameState state = x.stateBefore();
+        assert state != null : "deoptimize instruction always needs a state";
+
+        if (deoptimizationStubs == null) {
+            deoptimizationStubs = new ArrayList<DeoptimizationStub>();
+        }
+
+        // (tw) TODO: Try to reuse an existing stub if possible.
+        // It is only allowed if there are no LIR instructions in between that can modify registers.
+
+        DeoptimizationStub stub = new DeoptimizationStub(state);
+        deoptimizationStubs.add(stub);
+        lir.branch(x.condition.negate(), stub.label, stub.info);
+    }
+
+    public void doBlock(BlockBegin block) {
+        blockDoProlog(block);
+        this.currentBlock = block;
+
+        for (Instruction instr = block; instr != null; instr = instr.next()) {
+            if (instr.isLive()) {
+                walkState(instr, instr.stateBefore());
+                doRoot(instr);
+            }
+        }
+
+        this.currentBlock = null;
+        blockDoEpilog(block);
+    }
+
+    @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, x.needsNullCheck() ? stateFor(x) : null, null, true);
+        return x.operand();
+    }
+
+    @Override
+    public void visitBase(Base x) {
+        // emit phi-instruction move after safepoint since this simplifies
+        // describing the state at the safepoint.
+        moveToPhi(x.stateAfter());
+
+        // all blocks with a successor must end with an unconditional jump
+        // to the successor even if they are consecutive
+        lir.jump(x.defaultSuccessor());
+    }
+
+    private void setOperandsForLocals(FrameState state) {
+        CiCallingConvention args = compilation.frameMap().incomingArguments();
+        int javaIndex = 0;
+        for (int i = 0; i < args.locations.length; i++) {
+            CiValue src = args.locations[i];
+            assert src.isLegal() : "check";
+
+            CiVariable dest = newVariable(src.kind.stackKind());
+            lir.move(src, dest, src.kind);
+
+            // Assign new location to Local instruction for this local
+            Value instr = state.localAt(javaIndex);
+            Local local = ((Local) instr);
+            CiKind kind = src.kind.stackKind();
+            assert kind == local.kind.stackKind() : "local type check failed";
+            if (local.isLive()) {
+                setResult(local, dest);
+            }
+            javaIndex += kind.jvmSlots;
+        }
+    }
+
+    @Override
+    public void visitResolveClass(ResolveClass i) {
+        LIRDebugInfo info = stateFor(i);
+        XirSnippet snippet = xir.genResolveClass(site(i), i.type, i.portion);
+        emitXir(snippet, i, info, null, 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 visitInstanceOf(InstanceOf x) {
+        XirArgument obj = toXirArgument(x.object());
+        XirSnippet snippet = xir.genInstanceOf(site(x), obj, toXirArgument(x.targetClassInstruction), x.targetClass());
+        emitXir(snippet, x, maybeStateFor(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, maybeStateFor(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, maybeStateFor(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, maybeStateFor(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.elementClass(), x.exactType());
+        emitXir(snippet, x, stateFor(x), null, true);
+    }
+
+    @Override
+    public void visitNewObjectArrayClone(NewObjectArrayClone x) {
+        XirArgument length = toXirArgument(x.length());
+        XirArgument referenceArray = toXirArgument(x.referenceArray());
+        XirSnippet snippet = xir.genNewObjectArrayClone(site(x), length, referenceArray);
+        emitXir(snippet, x, stateFor(x), null, true);
+    }
+
+    @Override
+    public void visitNewMultiArray(NewMultiArray x) {
+        XirArgument[] dims = new XirArgument[x.dimensions().length];
+
+        for (int i = 0; i < dims.length; i++) {
+            dims[i] = toXirArgument(x.dimensions()[i]);
+        }
+
+        XirSnippet snippet = xir.genNewMultiArray(site(x), dims, x.elementKind);
+        emitXir(snippet, x, stateFor(x), null, true);
+    }
+
+    @Override
+    public void visitConstant(Constant x) {
+        if (canInlineAsConstant(x)) {
+            //setResult(x, loadConstant(x));
+        } else {
+            CiValue res = x.operand();
+            if (!(res.isLegal())) {
+                res = x.asConstant();
+            }
+            if (res.isConstant()) {
+                if (isUsedForValue(x)) {
+                    CiVariable reg = createResultVariable(x);
+                    lir.move(res, reg);
+                } else {
+                    assert x.checkFlag(Value.Flag.LiveDeopt);
+                    x.setOperand(res);
+                }
+            } else {
+                setResult(x, (CiVariable) res);
+            }
+        }
+    }
+
+    @Override
+    public void visitExceptionObject(ExceptionObject x) {
+        assert currentBlock.isExceptionEntry() : "ExceptionObject only allowed in exception handler block";
+        assert currentBlock.next() == x : "ExceptionObject must be first instruction of block";
+
+        // no moves are created for phi functions at the begin of exception
+        // handlers, so assign operands manually here
+        currentBlock.stateBefore().forEachLivePhi(currentBlock, new PhiProcedure() {
+            public boolean doPhi(Phi phi) {
+                operandForPhi(phi);
+                return true;
+            }
+        });
+
+        XirSnippet snippet = xir.genExceptionObject(site(x));
+        emitXir(snippet, x, maybeStateFor(x), null, true);
+    }
+
+    @Override
+    public void visitGoto(Goto x) {
+        setNoResult(x);
+
+        if (currentBlock.next() instanceof OsrEntry) {
+            // need to free up storage used for OSR entry point
+            CiValue osrBuffer = currentBlock.next().operand();
+            callRuntime(CiRuntimeCall.OSRMigrationEnd, null, osrBuffer);
+            emitXir(xir.genSafepoint(site(x)), x, stateFor(x, x.stateAfter()), null, false);
+        }
+
+        // emit phi-instruction moves after safepoint since this simplifies
+        // describing the state at the safepoint.
+        moveToPhi(x.stateAfter());
+
+        lir.jump(x.defaultSuccessor());
+    }
+
+    @Override
+    public void visitIfOp(IfOp 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);
+    }
+
+    @Override
+    public void visitIntrinsic(Intrinsic x) {
+        Value[] vals = x.arguments();
+        XirSnippet snippet;
+
+        switch (x.intrinsic()) {
+            case java_lang_Float$intBitsToFloat:
+            case java_lang_Double$doubleToRawLongBits:
+            case java_lang_Double$longBitsToDouble:
+            case java_lang_Float$floatToRawIntBits: {
+                visitFPIntrinsics(x);
+                return;
+            }
+
+            case java_lang_System$currentTimeMillis: {
+                assert x.numberOfArguments() == 0 : "wrong type";
+                CiValue reg = callRuntimeWithResult(CiRuntimeCall.JavaTimeMillis, null, (CiValue[]) null);
+                CiValue result = createResultVariable(x);
+                lir.move(reg, result);
+                return;
+            }
+
+            case java_lang_System$nanoTime: {
+                assert x.numberOfArguments() == 0 : "wrong type";
+                CiValue reg = callRuntimeWithResult(CiRuntimeCall.JavaTimeNanos, null, (CiValue[]) null);
+                CiValue result = createResultVariable(x);
+                lir.move(reg, result);
+                return;
+            }
+
+            case java_lang_Object$init:
+                visitRegisterFinalizer(x);
+                return;
+
+            case java_lang_Math$log:   // fall through
+            case java_lang_Math$log10: // fall through
+            case java_lang_Math$abs:   // fall through
+            case java_lang_Math$sqrt:  // fall through
+            case java_lang_Math$tan:   // fall through
+            case java_lang_Math$sin:   // fall through
+            case java_lang_Math$cos:
+                genMathIntrinsic(x);
+                return;
+
+            case sun_misc_Unsafe$compareAndSwapObject:
+                genCompareAndSwap(x, CiKind.Object);
+                return;
+            case sun_misc_Unsafe$compareAndSwapInt:
+                genCompareAndSwap(x, CiKind.Int);
+                return;
+            case sun_misc_Unsafe$compareAndSwapLong:
+                genCompareAndSwap(x, CiKind.Long);
+                return;
+
+            case java_lang_Thread$currentThread:
+                snippet = xir.genCurrentThread(site(x));
+                if (snippet != null) {
+                    emitXir(snippet, x, null, null, true);
+                    return;
+                }
+                break;
+
+            case java_lang_Object$getClass:
+                snippet = xir.genGetClass(site(x), toXirArgument(vals[0]));
+                if (snippet != null) {
+                    emitXir(snippet, x, stateFor(x), null, true);
+                    return;
+                }
+                break;
+        }
+
+
+        XirArgument[] args = new XirArgument[vals.length];
+        for (int i = 0; i < vals.length; i++) {
+            args[i] = toXirArgument(vals[i]);
+        }
+        snippet = xir.genIntrinsic(site(x), args, x.target());
+        if (snippet != null) {
+            emitXir(snippet, x, x.stateBefore() == null ? null : stateFor(x), null, true);
+            return;
+        }
+        x.setOperand(emitInvokeKnown(x.target(), x.stateBefore(), vals));
+    }
+
+    @Override
+    public void visitInvoke(Invoke x) {
+        RiMethod target = x.target();
+        LIRDebugInfo info = stateFor(x, x.stateBefore());
+
+        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 (!C1XOptions.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.arguments(), pointerSlots);
+
+        if (C1XOptions.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, info, snippet.marks, pointerSlots);
+        } else {
+            // Indirect call
+            argList.add(destinationAddress);
+            lir.callIndirect(target, resultOperand, argList, info, snippet.marks, pointerSlots);
+        }
+
+        if (resultOperand.isLegal()) {
+            CiValue result = createResultVariable(x);
+            lir.move(resultOperand, result);
+        }
+    }
+
+    @Override
+    public void visitNativeCall(NativeCall x) {
+        LIRDebugInfo info = stateFor(x, x.stateBefore());
+        CiValue resultOperand = resultOperandFor(x.kind);
+        CiValue callAddress = load(x.address());
+        CiKind[] signature = Util.signatureToKinds(x.signature, null);
+        CiCallingConvention cc = compilation.frameMap().getCallingConvention(signature, NativeCall);
+        List<CiValue> argList = visitInvokeArguments(cc, x.arguments, null);
+        argList.add(callAddress);
+        lir.callNative(x.nativeMethod.jniSymbol(), resultOperand, argList, info, null);
+        if (resultOperand.isLegal()) {
+            CiValue result = createResultVariable(x);
+            lir.move(resultOperand, result);
+        }
+    }
+
+    @Override
+    public void visitTemplateCall(TemplateCall x) {
+        CiValue resultOperand = resultOperandFor(x.kind);
+        List<CiValue> argList;
+        if (x.receiver() != null) {
+            CiCallingConvention cc = compilation.frameMap().getCallingConvention(new CiKind[] {CiKind.Object}, JavaCall);
+            argList = visitInvokeArguments(cc, new Value[] {x.receiver()}, null);
+        } else {
+            argList = new ArrayList<CiValue>();
+        }
+
+        if (x.address() != null) {
+            CiValue callAddress = load(x.address());
+            argList.add(callAddress);
+        }
+        lir.templateCall(resultOperand, argList);
+        if (resultOperand.isLegal()) {
+            CiValue result = createResultVariable(x);
+            lir.move(resultOperand, result);
+        }
+    }
+
+    @Override
+    public void visitLoadRegister(LoadRegister x) {
+        x.setOperand(x.register.asValue(x.kind));
+    }
+
+    @Override
+    public void visitPause(Pause i) {
+        lir.pause();
+    }
+
+    @Override
+    public void visitBreakpointTrap(BreakpointTrap i) {
+        lir.breakpoint();
+    }
+
+    protected CiAddress getAddressForPointerOp(PointerOp x, CiKind kind, CiValue pointer) {
+        CiAddress addr;
+        Value offset = x.offset();
+        Value index = x.index();
+        if (x.displacement() == null) {
+            // address is [pointer + offset]
+            if (offset.isConstant() && offset.kind.isInt()) {
+                int displacement = x.offset().asConstant().asInt();
+                addr = new CiAddress(kind, pointer, displacement);
+            } else {
+                addr = new CiAddress(kind, pointer, load(offset));
+            }
+        } else {
+            // address is [pointer + disp + (index * scale)]
+            assert (x.opcode & 0xff) == PGET || (x.opcode & 0xff) == PSET;
+            if (!x.displacement().isConstant()) {
+                CiVariable tmp = newVariable(CiKind.Word);
+                arithmeticOpLong(Bytecodes.LADD, tmp, pointer, load(x.displacement()), null);
+                int kindSize = compilation.target.sizeInBytes(kind);
+                Scale scale = Scale.fromInt(kindSize);
+                if (index.isConstant()) {
+                    addr = new CiAddress(kind, tmp, index.asConstant().asInt() * kindSize);
+                } else {
+                    addr = new CiAddress(kind, tmp, load(index), scale, 0);
+                }
+            } else {
+                int displacement = x.displacement().asConstant().asInt();
+                int kindSize = compilation.target.sizeInBytes(kind);
+                Scale scale = Scale.fromInt(kindSize);
+                if (index.isConstant()) {
+                    displacement += index.asConstant().asInt() * kindSize;
+                    addr = new CiAddress(kind, pointer, displacement);
+                } else {
+                    addr = new CiAddress(kind, pointer, load(index), scale, displacement);
+                }
+            }
+        }
+        return addr;
+    }
+
+    @Override
+    public void visitAllocateStackHandle(StackHandle x) {
+        CiValue value = load(x.value());
+        CiValue src = forceToSpill(value, x.value().kind, true);
+        CiValue dst = createResultVariable(x);
+
+        CiConstant constant = x.value().isConstant() ? x.value().asConstant() : null;
+        if (constant == null) {
+            CiConstant zero = CiConstant.defaultValue(x.value().kind);
+            lir.cmp(Condition.EQ, src, zero);
+        }
+        lir.lea(src, dst);
+        if (constant != null) {
+            if (constant.isDefaultValue()) {
+                lir.move(value, dst);
+            }
+        } else {
+            lir.cmove(Condition.EQ, CiConstant.ZERO, dst, dst);
+        }
+    }
+
+    @Override
+    public void visitLoadPointer(LoadPointer x) {
+        LIRDebugInfo info = maybeStateFor(x);
+        CiValue pointer = load(x.pointer());
+        CiValue dst = createResultVariable(x);
+        CiAddress src = getAddressForPointerOp(x, x.dataKind, pointer);
+        lir.load(src, dst, info);
+    }
+
+    @Override
+    public void visitStorePointer(StorePointer x) {
+        LIRDebugInfo info = maybeStateFor(x);
+        LIRItem value = new LIRItem(x.value(), this);
+        CiValue pointer = load(x.pointer());
+        value.loadItem(x.dataKind);
+        CiAddress dst = getAddressForPointerOp(x, x.dataKind, pointer);
+        lir.store(value.result(), dst, info);
+    }
+
+    @Override
+    public void visitInfopoint(Infopoint x) {
+        LIRDebugInfo info = stateFor(x);
+        if (x.opcode == SAFEPOINT) {
+            emitXir(xir.genSafepoint(site(x)), x, info, null, false);
+            return;
+        }
+        assert x.opcode == HERE || x.opcode == INFO;
+        CiValue result = x.kind.isVoid() ? CiValue.IllegalValue : createResultVariable(x);
+        LIROpcode opcode = x.opcode == HERE ? LIROpcode.Here : LIROpcode.Info;
+        lir.infopoint(opcode, result, info);
+    }
+
+    @Override
+    public void visitStackAllocate(StackAllocate x) {
+        CiValue result = createResultVariable(x);
+        assert x.size().isConstant() : "ALLOCA bytecode 'size' operand is not a constant: " + x.size();
+        StackBlock stackBlock = compilation.frameMap().reserveStackBlock(x.size().asConstant().asInt());
+        lir.alloca(stackBlock, result);
+    }
+
+    @Override
+    public void visitMonitorAddress(MonitorAddress x) {
+        CiValue result = createResultVariable(x);
+        lir.monitorAddress(x.monitor(), result);
+    }
+
+    @Override
+    public void visitMemoryBarrier(MemoryBarrier x) {
+        if (x.barriers != 0) {
+            lir.membar(x.barriers);
+        }
+    }
+
+    @Override
+    public void visitUnsafeCast(UnsafeCast i) {
+        assert !i.redundant : "redundant UnsafeCasts must be eliminated by the front end";
+        CiValue src = load(i.value());
+        CiValue dst = createResultVariable(i);
+        lir.move(src, dst);
+    }
+
+    /**
+     * For note on volatile fields, see {@link #visitStoreField(StoreField)}.
+     */
+    @Override
+    public void visitLoadField(LoadField x) {
+        RiField field = x.field();
+        boolean needsPatching = x.needsPatching();
+        LIRDebugInfo info = null;
+        if (needsPatching || x.needsNullCheck()) {
+            info = stateFor(x, x.stateBefore());
+            assert info != null;
+        }
+
+        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, maybeStateFor(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.isSafepoint()) {
+            emitXir(xir.genSafepoint(site(x)), x, stateFor(x, x.stateAfter()), null, false);
+        }
+
+        // move values into phi locations
+        moveToPhi(x.stateAfter());
+
+        if (x.numberOfCases() == 0 || x.numberOfCases() < C1XOptions.SequentialSwitchLimit) {
+            int len = x.numberOfCases();
+            for (int i = 0; i < len; i++) {
+                lir.cmp(Condition.EQ, tag, x.keyAt(i));
+                lir.branch(Condition.EQ, CiKind.Int, x.suxAt(i));
+            }
+            lir.jump(x.defaultSuccessor());
+        } else {
+            visitSwitchRanges(createLookupRanges(x), tag, x.defaultSuccessor());
+        }
+    }
+
+    @Override
+    public void visitNullCheck(NullCheck x) {
+        // TODO: this is suboptimal because it may result in an unnecessary move
+        CiValue value = load(x.object());
+        if (x.canTrap()) {
+            LIRDebugInfo info = stateFor(x);
+            lir.nullCheck(value, info);
+        }
+        x.setOperand(value);
+    }
+
+    @Override
+    public void visitOsrEntry(OsrEntry x) {
+        // construct our frame and model the production of incoming pointer
+        // to the OSR buffer.
+        lir.osrEntry(osrBufferPointer());
+        CiValue result = createResultVariable(x);
+        lir.move(osrBufferPointer(), result);
+    }
+
+    @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, stateFor(x, x.stateAfter()), 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, stateFor(x, x.stateAfter()), 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 {
+                item.loadItem(var.kind);
+                return item.result();
+            }
+        }
+    }
+
+    protected CiValue emitXir(XirSnippet snippet, Instruction x, LIRDebugInfo info, RiMethod method, boolean setInstructionResult) {
+        return emitXir(snippet, x, info, null, method, setInstructionResult, null);
+    }
+
+    protected CiValue emitXir(XirSnippet snippet, Instruction instruction, LIRDebugInfo info, LIRDebugInfo infoAfter, RiMethod method, boolean setInstructionResult, List<CiValue> pointerSlots) {
+        if (C1XOptions.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 (C1XOptions.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 (C1XOptions.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 (C1XOptions.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 (C1XOptions.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 visitIncrementRegister(IncrementRegister x) {
+        CiValue reg = x.register.asValue(CiKind.Word);
+        if (x.delta().isConstant()) {
+            int delta = x.delta().asConstant().asInt();
+            if (delta < 0) {
+                lir.sub(reg, CiConstant.forInt(-delta), reg);
+            } else {
+                lir.add(reg, CiConstant.forInt(delta), reg);
+            }
+        } else {
+            lir.add(reg, makeOperand(x.delta()), reg);
+        }
+    }
+
+    @Override
+    public void visitStoreRegister(StoreRegister x) {
+        CiValue reg = x.register.asValue(x.kind);
+        lir.move(makeOperand(x.value()), reg);
+    }
+
+    @Override
+    public void visitStoreField(StoreField x) {
+        RiField field = x.field();
+        boolean needsPatching = x.needsPatching();
+
+        LIRDebugInfo info = null;
+        if (needsPatching || x.needsNullCheck()) {
+            info = stateFor(x, x.stateBefore());
+        }
+
+        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);
+
+        if (x.isSafepoint()) {
+            emitXir(xir.genSafepoint(site(x)), x, stateFor(x, x.stateAfter()), null, false);
+        }
+
+        // move values into phi locations
+        moveToPhi(x.stateAfter());
+
+        // TODO: tune the defaults for the controls used to determine what kind of translation to use
+        if (x.numberOfCases() == 0 || x.numberOfCases() <= C1XOptions.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, CiKind.Int, x.suxAt(i));
+            }
+            lir.jump(x.defaultSuccessor());
+        } else {
+            SwitchRange[] switchRanges = createLookupRanges(x);
+            int rangeDensity = x.numberOfCases() / switchRanges.length;
+            if (rangeDensity >= C1XOptions.RangeTestsSwitchDensity) {
+                visitSwitchRanges(switchRanges, tag, x.defaultSuccessor());
+            } else {
+                List<BlockBegin> nonDefaultSuccessors = x.successors().subList(0, x.numberOfCases());
+                BlockBegin[] targets = nonDefaultSuccessors.toArray(new BlockBegin[nonDefaultSuccessors.size()]);
+                lir.tableswitch(tag, x.lowKey(), x.defaultSuccessor(), targets);
+            }
+        }
+    }
+
+    @Override
+    public void visitThrow(Throw x) {
+        setNoResult(x);
+        CiValue exceptionOpr = load(x.exception());
+        LIRDebugInfo info = stateFor(x, x.stateAfter());
+
+        // check if the instruction has an xhandler in any of the nested scopes
+        boolean unwind = false;
+        if (x.exceptionHandlers().size() == 0) {
+            // this throw is not inside an xhandler
+            unwind = true;
+        } else {
+            // get some idea of the throw type
+            boolean typeIsExact = true;
+            RiType throwType = x.exception().exactType();
+            if (throwType == null) {
+                typeIsExact = false;
+                throwType = x.exception().declaredType();
+            }
+            if (throwType != null && throwType.isResolved() && throwType.isInstanceClass()) {
+                unwind = !ExceptionHandler.couldCatch(x.exceptionHandlers(), throwType, typeIsExact);
+            }
+        }
+
+        assert !currentBlock.checkBlockFlag(BlockBegin.BlockFlag.DefaultExceptionHandler) || unwind : "should be no more handlers to dispatch to";
+
+        // move exception oop into fixed register
+        CiCallingConvention callingConvention = compilation.frameMap().getCallingConvention(new CiKind[]{CiKind.Object}, RuntimeCall);
+        CiValue argumentOperand = callingConvention.locations[0];
+        lir.move(exceptionOpr, argumentOperand);
+
+        if (unwind) {
+            lir.unwindException(exceptionPcOpr(), exceptionOpr, info);
+        } else {
+            lir.throwException(exceptionPcOpr(), argumentOperand, info);
+        }
+    }
+
+    @Override
+    public void visitUnsafeGetObject(UnsafeGetObject x) {
+        CiKind kind = x.unsafeOpKind;
+
+        CiValue off = load(x.offset());
+        CiValue src = load(x.object());
+
+        CiValue reg = createResultVariable(x);
+
+        if (x.isVolatile()) {
+            vma.preVolatileRead();
+        }
+        genGetObjectUnsafe(reg, src, off, kind, x.isVolatile());
+        if (x.isVolatile()) {
+            vma.postVolatileRead();
+        }
+    }
+
+    @Override
+    public void visitUnsafeGetRaw(UnsafeGetRaw x) {
+        LIRItem idx = new LIRItem(this);
+        CiValue base = load(x.base());
+        if (x.hasIndex()) {
+            idx.setInstruction(x.index());
+            idx.loadNonconstant();
+        }
+
+        CiValue reg = createResultVariable(x);
+
+        int log2scale = 0;
+        if (x.hasIndex()) {
+            assert x.index().kind.isInt() : "should not find non-int index";
+            log2scale = x.log2Scale();
+        }
+
+        assert !x.hasIndex() || idx.instruction == x.index() : "should match";
+
+        CiKind dstKind = x.unsafeOpKind;
+        CiValue indexOp = idx.result();
+
+        CiAddress addr = null;
+        if (indexOp.isConstant()) {
+            assert log2scale == 0 : "must not have a scale";
+            CiConstant constantIndexOp = (CiConstant) indexOp;
+            addr = new CiAddress(dstKind, base, constantIndexOp.asInt());
+        } else {
+
+            if (compilation.target.arch.isX86()) {
+                addr = new CiAddress(dstKind, base, indexOp, CiAddress.Scale.fromInt(2 ^ log2scale), 0);
+
+            } else if (compilation.target.arch.isSPARC()) {
+                if (indexOp.isIllegal() || log2scale == 0) {
+                    addr = new CiAddress(dstKind, base, indexOp);
+                } else {
+                    CiValue tmp = newVariable(CiKind.Int);
+                    lir.shiftLeft(indexOp, log2scale, tmp);
+                    addr = new CiAddress(dstKind, base, tmp);
+                }
+
+            } else {
+                Util.shouldNotReachHere();
+            }
+        }
+
+        if (x.mayBeUnaligned() && (dstKind == CiKind.Long || dstKind == CiKind.Double)) {
+            lir.unalignedMove(addr, reg);
+        } else {
+            lir.move(addr, reg);
+        }
+    }
+
+    @Override
+    public void visitUnsafePrefetchRead(UnsafePrefetchRead x) {
+        visitUnsafePrefetch(x, false);
+    }
+
+    @Override
+    public void visitUnsafePrefetchWrite(UnsafePrefetchWrite x) {
+        visitUnsafePrefetch(x, true);
+    }
+
+    @Override
+    public void visitUnsafePutObject(UnsafePutObject x) {
+        CiKind kind = x.unsafeOpKind;
+        LIRItem data = new LIRItem(x.value(), this);
+
+        CiValue src = load(x.object());
+        data.loadItem(kind);
+        CiValue off = load(x.offset());
+
+        setNoResult(x);
+
+        if (x.isVolatile()) {
+            vma.preVolatileWrite();
+        }
+        genPutObjectUnsafe(src, off, data.result(), kind, x.isVolatile());
+        if (x.isVolatile()) {
+            vma.postVolatileWrite();
+        }
+    }
+
+    @Override
+    public void visitUnsafePutRaw(UnsafePutRaw x) {
+        int log2scale = 0;
+        CiKind kind = x.unsafeOpKind;
+
+        if (x.hasIndex()) {
+            assert x.index().kind.isInt() : "should not find non-int index";
+            log2scale = x.log2scale();
+        }
+
+        LIRItem value = new LIRItem(x.value(), this);
+        LIRItem idx = new LIRItem(this);
+
+        CiValue base = load(x.base());
+        if (x.hasIndex()) {
+            idx.setInstruction(x.index());
+            idx.loadItem();
+        }
+
+        value.loadItem(kind);
+
+        setNoResult(x);
+
+        CiValue indexOp = idx.result();
+        if (log2scale != 0) {
+            // temporary fix (platform dependent code without shift on Intel would be better)
+            indexOp = newVariable(CiKind.Int);
+            lir.move(idx.result(), indexOp);
+            lir.shiftLeft(indexOp, log2scale, indexOp);
+        }
+
+        CiValue addr = new CiAddress(x.unsafeOpKind, base, indexOp);
+        lir.move(value.result(), addr);
+    }
+
+    private void blockDoEpilog(BlockBegin block) {
+        if (C1XOptions.PrintIRWithLIR) {
+            TTY.println();
+        }
+
+        // clear out variables for local constants
+        constants.clear();
+        variablesForConstants.clear();
+    }
+
+    private void blockDoProlog(BlockBegin block) {
+        if (C1XOptions.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());
+        if (block == ir.startBlock) {
+            XirSnippet prologue = xir.genPrologue(null, compilation.method);
+            if (prologue != null) {
+                emitXir(prologue, null, null, null, false);
+            }
+            setOperandsForLocals(block.end().stateAfter());
+        }
+    }
+
+    /**
+     * 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}
+     */
+    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) {
+            C1XMetrics.LoadConstantIterations += index;
+            return variablesForConstants.get(index);
+        }
+        C1XMetrics.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}
+     */
+    protected CiVariable createResultVariable(Value x) {
+        CiVariable operand = newVariable(x.kind);
+        setResult(x, operand);
+        return operand;
+    }
+
+    private void visitFPIntrinsics(Intrinsic x) {
+        assert x.numberOfArguments() == 1 : "wrong type";
+        CiValue reg = createResultVariable(x);
+        CiValue value = load(x.argumentAt(0));
+        CiValue tmp = forceToSpill(value, x.kind, false);
+        lir.move(tmp, reg);
+    }
+
+    private void visitRegisterFinalizer(Intrinsic x) {
+        assert x.numberOfArguments() == 1 : "wrong type";
+        CiValue receiver = load(x.argumentAt(0));
+        LIRDebugInfo info = stateFor(x, x.stateBefore());
+        callRuntime(CiRuntimeCall.RegisterFinalizer, info, receiver);
+        setNoResult(x);
+    }
+
+    private void visitSwitchRanges(SwitchRange[] x, CiValue value, BlockBegin defaultSux) {
+        for (int i = 0; i < x.length; i++) {
+            SwitchRange oneRange = x[i];
+            int lowKey = oneRange.lowKey;
+            int highKey = oneRange.highKey;
+            BlockBegin dest = oneRange.sux;
+            if (lowKey == highKey) {
+                lir.cmp(Condition.EQ, value, lowKey);
+                lir.branch(Condition.EQ, CiKind.Int, dest);
+            } else if (highKey - lowKey == 1) {
+                lir.cmp(Condition.EQ, value, lowKey);
+                lir.branch(Condition.EQ, CiKind.Int, dest);
+                lir.cmp(Condition.EQ, value, highKey);
+                lir.branch(Condition.EQ, CiKind.Int, 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, CiKind.Int, dest);
+                lir.branchDestination(l);
+            }
+        }
+        lir.jump(defaultSux);
+    }
+
+    private void visitUnsafePrefetch(UnsafePrefetch x, boolean isStore) {
+        LIRItem src = new LIRItem(x.object(), this);
+        LIRItem off = new LIRItem(x.offset(), this);
+
+        src.loadItem();
+        if (!(off.result().isConstant() && canInlineAsConstant(x.offset()))) {
+            off.loadItem();
+        }
+
+        setNoResult(x);
+
+        CiAddress addr = genAddress(src.result(), off.result(), 0, 0, CiKind.Byte);
+        lir.prefetch(addr, isStore);
+    }
+
+    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();
+        }
+    }
+
+    protected 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();
+        }
+    }
+
+    protected void arithmeticOpLong(int code, CiValue result, CiValue left, CiValue right, LIRDebugInfo info) {
+        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) {
+            BlockBegin defaultSux = x.defaultSuccessor();
+            int key = x.keyAt(0);
+            BlockBegin sux = x.suxAt(0);
+            SwitchRange range = new SwitchRange(key, sux);
+            for (int i = 1; i < len; i++) {
+                int newKey = x.keyAt(i);
+                BlockBegin newSux = x.suxAt(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) {
+            BlockBegin sux = x.suxAt(0);
+            int key = x.lowKey();
+            BlockBegin defaultSux = x.defaultSuccessor();
+            SwitchRange range = new SwitchRange(key, sux);
+            for (int i = 0; i < len; i++, key++) {
+                BlockBegin newSux = x.suxAt(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(Instruction instr) {
+        currentInstruction = instr;
+        assert instr.isLive() : "use only with roots";
+        assert !instr.hasSubst() : "shouldn't have missed substitution";
+
+        if (C1XOptions.TraceLIRVisit) {
+            TTY.println("Visiting    " + instr);
+        }
+        instr.accept(this);
+        if (C1XOptions.TraceLIRVisit) {
+            TTY.println("Operand for " + instr + " = " + instr.operand());
+        }
+
+        assert (instr.operand().isLegal()) || !isUsedForValue(instr) || instr.isConstant() || instr instanceof UnsafeCast : "operand was not set for live instruction";
+    }
+
+    private boolean isUsedForValue(Instruction instr) {
+        return instr.checkFlag(Value.Flag.LiveValue);
+    }
+
+    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) {
+        // 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.isLive() && curVal != null && curVal != phi) {
+                assert curVal.isLive() : "value not live: " + curVal + ", suxVal=" + suxVal;
+                assert !phi.isIllegal() : "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));
+            }
+        }
+    }
+
+    protected void moveToPhi(FrameState curState) {
+        // Moves all stack values into their phi position
+        BlockBegin bb = currentBlock;
+        if (bb.numberOfSux() == 1) {
+            BlockBegin sux = bb.suxAt(0);
+            assert sux.numberOfPreds() > 0 : "invalid CFG";
+
+            // a block with only one predecessor never has phi functions
+            if (sux.numberOfPreds() > 1) {
+                PhiResolver resolver = new PhiResolver(this);
+
+                FrameState suxState = sux.stateBefore();
+
+                for (int index = 0; index < suxState.stackSize(); index++) {
+                    moveToPhi(resolver, curState.stackAt(index), suxState.stackAt(index));
+                }
+
+                // walk up the inlined scopes until locals match
+                while (curState.scope() != suxState.scope()) {
+                    curState = curState.callerState();
+                    assert curState != null : "scopes don't match up";
+                }
+
+                for (int index = 0; index < suxState.localsSize(); index++) {
+                    moveToPhi(resolver, curState.localAt(index), suxState.localAt(index));
+                }
+
+                assert curState.scope().callerState == suxState.scope().callerState : "caller states must be equal";
+                resolver.dispose();
+            }
+        }
+    }
+
+    /**
+     * 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";
+                // allocate a variable for this local or phi
+                createResultVariable(x);
+            }
+        }
+        return x.operand();
+    }
+
+    private CiValue operandForPhi(Phi phi) {
+        if (phi.operand().isIllegal()) {
+            // allocate a variable for this phi
+            CiVariable operand = newVariable(phi.kind);
+            setResult(phi, operand);
+        }
+        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(Instruction x) {
+        assert !isUsedForValue(x) : "can't have use";
+        x.clearOperand();
+    }
+
+    protected CiValue setResult(Value x, CiVariable operand) {
+        x.setOperand(operand);
+        if (C1XOptions.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(Instruction x, FrameState state) {
+        if (state == null) {
+            return;
+        }
+        for (int index = 0; index < state.stackSize(); index++) {
+            walkStateValue(state.stackAt(index));
+        }
+        FrameState s = state;
+        int bci = x.bci();
+
+        while (s != null) {
+            IRScope scope = s.scope();
+            if (bci == Instruction.SYNCHRONIZATION_ENTRY_BCI) {
+                assert x instanceof ExceptionObject ||
+                       x instanceof Throw ||
+                       x instanceof MonitorEnter ||
+                       x instanceof MonitorExit;
+            }
+
+            for (int index = 0; index < s.localsSize(); index++) {
+                final Value value = s.localAt(index);
+                if (value != null) {
+                    if (!value.isIllegal()) {
+                        walkStateValue(value);
+                    }
+                }
+            }
+            bci = scope.callerBCI();
+            s = s.callerState();
+        }
+    }
+
+    private void walkStateValue(Value value) {
+        if (value != null) {
+            assert !value.hasSubst() : "missed substitution";
+            assert value.isLive() : "value must be marked live in frame state";
+            if (value instanceof Phi && !value.isIllegal()) {
+                // phi's are special
+                operandForPhi((Phi) value);
+            } else if (value.operand().isIllegal() && !(value instanceof UnsafeCast)) {
+                // instruction doesn't have an operand yet
+                CiValue operand = makeOperand(value);
+                assert operand.isLegal() : "must be evaluated now";
+            }
+        }
+    }
+
+    protected LIRDebugInfo maybeStateFor(Instruction x) {
+        FrameState stateBefore = x.stateBefore();
+        if (stateBefore == null) {
+            return null;
+        }
+        return stateFor(x, stateBefore);
+    }
+
+    protected LIRDebugInfo stateFor(Instruction x) {
+        assert x.stateBefore() != null : "must have state before instruction for " + x;
+        return stateFor(x, x.stateBefore());
+    }
+
+    protected LIRDebugInfo stateFor(Instruction x, FrameState state) {
+        if (compilation.placeholderState != null) {
+            state = compilation.placeholderState;
+        }
+
+        return new LIRDebugInfo(state, x.exceptionHandlers());
+    }
+
+    List<CiValue> visitInvokeArguments(CiCallingConvention cc, Value[] args, List<CiValue> pointerSlots) {
+        // for each argument, load it into the correct location
+        List<CiValue> argList = new ArrayList<CiValue>(args.length);
+        int j = 0;
+        for (Value arg : args) {
+            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 explicitedly 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
+     */
+    protected CiValue makeOperand(Value instruction) {
+        assert instruction.isLive();
+        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";
+        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 CiValue exceptionPcOpr();
+
+    protected abstract CiValue osrBufferPointer();
+
+    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);
+
+    protected abstract void genGetObjectUnsafe(CiValue dest, CiValue src, CiValue offset, CiKind kind, boolean isVolatile);
+
+    protected abstract void genPutObjectUnsafe(CiValue src, CiValue offset, CiValue data, CiKind kind, boolean isVolatile);
+
+    protected abstract void genCompareAndSwap(Intrinsic x, CiKind kind);
+
+    protected abstract void genMathIntrinsic(Intrinsic x);
+
+    /**
+     * 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) {
+            if (argument.constant == null && argument.object instanceof LIRItem) {
+                // check the flag on the original value
+                return ((LIRItem) argument.object).instruction.isNonNull();
+            }
+            return false;
+        }
+
+        public boolean requiresNullCheck() {
+            return current == null || current.needsNullCheck();
+        }
+
+        public boolean requiresBoundsCheck() {
+            return current == null || !current.checkFlag(Value.Flag.NoBoundsCheck);
+        }
+
+        public boolean requiresReadBarrier() {
+            return current == null || !current.checkFlag(Value.Flag.NoReadBarrier);
+        }
+
+        public boolean requiresWriteBarrier() {
+            return current == null || !current.checkFlag(Value.Flag.NoWriteBarrier);
+        }
+
+        public boolean requiresArrayStoreCheck() {
+            return current == null || !current.checkFlag(Value.Flag.NoStoreCheck);
+        }
+
+        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 + ">";
+        }
+
+    }
+
+    public void arrayCopy(RiType type, ArrayCopy arrayCopy, XirSnippet snippet) {
+        emitXir(snippet, arrayCopy, stateFor(arrayCopy), null, false);
+    }
+
+    @Override
+    public void visitArrayCopy(ArrayCopy arrayCopy) {
+        Value src = arrayCopy.src();
+        Value dest = arrayCopy.dest();
+        Value srcPos = arrayCopy.srcPos();
+        Value destPos = arrayCopy.destPos();
+        Value length = arrayCopy.length();
+        RiType srcType = src.declaredType();
+        RiType destType = dest.declaredType();
+        if ((srcType != null && srcType.isArrayClass()) || (destType != null && destType.isArrayClass())) {
+            RiType type = (srcType == null) ? destType : srcType;
+            if ((srcType == null || destType == null || srcType.kind() != destType.kind()) && type.kind() != CiKind.Object) {
+                TypeEqualityCheck typeCheck = new TypeEqualityCheck(src, dest, arrayCopy.stateBefore(), Condition.EQ);
+                visitTypeEqualityCheck(typeCheck);
+            }
+            boolean inputsSame = (src == dest);
+            boolean inputsDifferent = !inputsSame && (src.checkFlag(Flag.ResultIsUnique) || dest.checkFlag(Flag.ResultIsUnique));
+            boolean needsStoreCheck = type.componentType().kind() == CiKind.Object && destType != srcType;
+            if (!needsStoreCheck) {
+                arrayCopy.setFlag(Flag.NoStoreCheck);
+            }
+            XirSnippet snippet = xir.genArrayCopy(site(arrayCopy), toXirArgument(src), toXirArgument(srcPos), toXirArgument(dest), toXirArgument(destPos), toXirArgument(length), type.componentType(), inputsSame, inputsDifferent);
+            arrayCopy(type, arrayCopy, snippet);
+            return;
+        }
+        arrayCopySlow(arrayCopy);
+    }
+
+    private void arrayCopySlow(ArrayCopy arrayCopy) {
+        emitInvokeKnown(arrayCopy.arrayCopyMethod, arrayCopy.stateBefore(), arrayCopy.src(), arrayCopy.srcPos(), arrayCopy.dest(), arrayCopy.destPos(), arrayCopy.length());
+    }
+
+    private CiValue emitInvokeKnown(RiMethod method, FrameState stateBefore, Value... args) {
+        boolean isStatic = Modifier.isStatic(method.accessFlags());
+        Invoke invoke = new Invoke(isStatic ? Bytecodes.INVOKESTATIC : Bytecodes.INVOKESPECIAL, method.signature().returnKind(), args, isStatic, method, null, stateBefore);
+        visitInvoke(invoke);
+        return invoke.operand();
+    }
+
+    @Override
+    public void visitTypeEqualityCheck(TypeEqualityCheck typeEqualityCheck) {
+        Value x = typeEqualityCheck.left();
+        Value y = typeEqualityCheck.right();
+
+        CiValue leftValue = emitXir(xir.genGetClass(site(typeEqualityCheck), toXirArgument(x)), typeEqualityCheck, stateFor(typeEqualityCheck), null, false);
+        CiValue rightValue = emitXir(xir.genGetClass(site(typeEqualityCheck), toXirArgument(y)), typeEqualityCheck, stateFor(typeEqualityCheck), null, false);
+        lir.cmp(typeEqualityCheck.condition.negate(), leftValue, rightValue);
+        emitGuard(typeEqualityCheck);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/gen/LIRItem.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.gen;
+
+import com.sun.c1x.alloc.OperandPool.*;
+import com.sun.c1x.ir.*;
+import com.sun.c1x.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 value, LIRGenerator gen) {
+        this.gen = gen;
+        setInstruction(value);
+    }
+
+    public void setInstruction(Value instruction) {
+        this.instruction = instruction;
+        if (instruction != null) {
+            resultOperand = gen.makeOperand(instruction);
+        } else {
+            resultOperand = CiValue.IllegalValue;
+        }
+        intermediateOperand = CiValue.IllegalValue;
+    }
+
+    public LIRItem(LIRGenerator gen) {
+        this.gen = gen;
+        setInstruction(null);
+    }
+
+    public void loadItem(CiKind kind) {
+        if (kind == CiKind.Byte || kind == CiKind.Boolean) {
+            loadByteItem();
+        } else {
+            loadItem();
+        }
+    }
+
+    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() {
+        if (gen.compilation.target.arch.isX86()) {
+            CiValue r = instruction.operand();
+            if (r.isConstant()) {
+                resultOperand = r;
+            } else {
+                loadItem();
+            }
+        } else if (gen.compilation.target.arch.isSPARC()) {
+            CiValue r = instruction.operand();
+            if (gen.canInlineAsConstant(instruction)) {
+                if (!r.isConstant()) {
+                    r = instruction.asConstant();
+                }
+                resultOperand = r;
+            } else {
+                loadItem();
+            }
+        } else {
+            Util.shouldNotReachHere();
+        }
+    }
+
+    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/Compiler/src/com/sun/c1x/gen/PhiResolver.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,238 @@
+/*
+ * 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.sun.c1x.gen;
+
+import static com.sun.cri.ci.CiValue.*;
+
+import java.util.*;
+
+import com.sun.c1x.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>
+ *
+ * @author Marcelo Cintra
+ * @author Thomas Wuerthinger
+ * @author Doug Simon
+ */
+public class PhiResolver {
+
+    /**
+     * Tracks a data flow dependency between a source operand and any number of the destination operands.
+     */
+    static class Node {
+
+        /**
+         * 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<Node> 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;
+
+        Node(CiValue operand) {
+            this.operand = operand;
+            destinations = new ArrayList<Node>(4);
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder buf = new StringBuilder(operand.toString());
+            if (!destinations.isEmpty()) {
+                buf.append(" ->");
+                for (Node 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 Node loop;
+
+    private CiValue temp;
+
+    private final ArrayList<Node> variableOperands = new ArrayList<Node>(3);
+    private final ArrayList<Node> otherOperands = new ArrayList<Node>(3);
+
+    /**
+     * Maps operands to nodes.
+     */
+    private final HashMap<CiValue, Node> operandToNodeMap = new HashMap<CiValue, Node>();
+
+    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--) {
+            Node 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--) {
+            Node 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";
+        Node srcNode = sourceNode(src);
+        Node destNode = destinationNode(dest);
+        srcNode.destinations.add(destNode);
+      }
+
+    private Node createNode(CiValue operand, boolean source) {
+        Node node;
+        if (operand.isVariable()) {
+            node = operandToNodeMap.get(operand);
+            assert node == null || node.operand.equals(operand);
+            if (node == null) {
+                node = new Node(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 Node(operand);
+            otherOperands.add(node);
+        }
+        return node;
+    }
+
+    private Node 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(Node src, Node 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 Node sourceNode(CiValue opr) {
+        return createNode(opr, true);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/gen/package-info.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.gen;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/globalstub/GlobalStub.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.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/Compiler/src/com/sun/c1x/globalstub/GlobalStubEmitter.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.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/Compiler/src/com/sun/c1x/graph/BlockMap.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,693 @@
+/*
+ * 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.sun.c1x.graph;
+
+import static com.sun.cri.bytecode.Bytecodes.*;
+
+import java.util.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.ir.*;
+import com.sun.c1x.util.*;
+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).
+ *
+ * A {@link BlockBegin} node with the {@link BlockFlag#StandardEntry} flag is created with bytecode index 0.
+ * Note this is distinct from the similar {@link BlockBegin} node assigned to {@link IR#startBlock} by
+ * {@link GraphBuilder}.
+ *
+ * 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.
+ *
+ * @author Ben L. Titzer
+ */
+public final class BlockMap {
+
+    private static final BlockBegin[] NONE = {};
+    private static final List<BlockBegin> NONE_LIST = Collections.emptyList();
+
+    /**
+     * The {@code ExceptionMap} class is used internally to track exception handlers
+     * while iterating over the bytecode and the control flow graph. Since methods with
+     * exception handlers are much less frequent than those without, the common case
+     * does not need to construct an exception map.
+     */
+    private class ExceptionMap {
+        private final CiBitMap canTrap;
+        private final boolean isObjectInit;
+        private final RiExceptionHandler[] allHandlers;
+        private final ArrayMap<HashSet<BlockBegin>> handlerMap;
+
+        ExceptionMap(RiMethod method, byte[] code) {
+            canTrap = new CiBitMap(code.length);
+            isObjectInit = C1XIntrinsic.getIntrinsic(method) == C1XIntrinsic.java_lang_Object$init;
+            allHandlers = method.exceptionHandlers();
+            handlerMap = new ArrayMap<HashSet<BlockBegin>>(firstBlock, firstBlock + code.length / 5);
+        }
+
+        void setCanTrap(int bci) {
+            canTrap.set(bci);
+        }
+
+        void addHandlers(BlockBegin block, int bci) {
+            if (canTrap.get(bci)) {
+                // XXX: replace with faster algorithm (sort exception handlers by start and end)
+                for (RiExceptionHandler h : allHandlers) {
+                    if (h.startBCI() <= bci && bci < h.endBCI()) {
+                        addHandler(block, get(h.handlerBCI()));
+                        if (h.isCatchAll()) {
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+
+        Collection<BlockBegin> getHandlers(BlockBegin block) {
+            // lookup handlers for the basic block
+            HashSet<BlockBegin> set = handlerMap.get(block.blockID);
+            return set == null ? NONE_LIST : set;
+        }
+
+        void setHandlerEntrypoints() {
+            // start basic blocks at all exception handler blocks and mark them as exception entries
+            for (RiExceptionHandler h : allHandlers) {
+                addEntrypoint(h.handlerBCI(), BlockBegin.BlockFlag.ExceptionEntry);
+            }
+        }
+
+        void addHandler(BlockBegin block, BlockBegin handler) {
+            // add a handler to a basic block, creating the set if necessary
+            HashSet<BlockBegin> set = handlerMap.get(block.blockID);
+            if (set == null) {
+                set = new HashSet<BlockBegin>();
+                handlerMap.put(block.blockID, set);
+            }
+            set.add(handler);
+        }
+    }
+
+    /** The bytecodes for the associated method. */
+    private final byte[] code;
+
+    /**
+     * Every {@link BlockBegin} node created by {@link BlockMap#build} has an entry in this
+     * array at the corresponding bytecode index. Length is same as {@link BlockMap#code}.
+     */
+    private final BlockBegin[] blockMap;
+
+    /**
+     * A bit map covering the locals with a bit set for each local that is
+     * stored to within a loop. This may be conservative depending on the value
+     * of the {@code computeStoresInLoops} parameters of {@link #build(boolean)}.
+     */
+    private final CiBitMap storesInLoops;
+
+    /**
+     * Every bytecode instruction that has zero, one or more successor nodes (e.g. {@link Bytecodes#GOTO} has one) has
+     * an entry in this array at the corresponding bytecode index. The value is another array of {@code BlockBegin} nodes,
+     * with length equal to the number of successors, whose entries are the {@code BlockBegin} nodes for the successor
+     * blocks. Length is same as {@link BlockMap#code}.
+     */
+    private BlockBegin[][] successorMap;
+
+    /** List of {@code BlockBegin} nodes that are inside loops. */
+    private ArrayList<BlockBegin> loopBlocks;
+    private ExceptionMap exceptionMap;
+
+    /**
+     * The first block number allocated for the blocks within this block map.
+     */
+    private final int firstBlock;
+
+    /**
+     * Used for initial block ID (count up) and post-order number (count down).
+     */
+    private int blockNum;
+
+    /**
+     * Creates a new BlockMap instance from bytecode of the given method .
+     * @param method the compiler interface method containing the code
+     * @param firstBlockNum the first block number to use when creating {@link BlockBegin} nodes
+     */
+    public BlockMap(RiMethod method, int firstBlockNum) {
+        byte[] code = method.code();
+        this.code = code;
+        firstBlock = firstBlockNum;
+        blockNum = firstBlockNum;
+        blockMap = new BlockBegin[code.length];
+        successorMap = new BlockBegin[code.length][];
+        storesInLoops = new CiBitMap(method.maxLocals());
+        if (method.exceptionHandlers().length != 0) {
+            exceptionMap = new ExceptionMap(method, code);
+        }
+    }
+
+    /**
+     * Add an entrypoint to this BlockMap. The resulting block will be marked
+     * with the specified block flags.
+     * @param bci the bytecode index of the start of the block
+     * @param entryFlag the entry flag to mark the block with
+     */
+    public void addEntrypoint(int bci, BlockBegin.BlockFlag entryFlag) {
+        make(bci).setBlockFlag(entryFlag);
+    }
+
+    /**
+     * Gets the block that begins at the specified bytecode index.
+     * @param bci the bytecode index of the start of the block
+     * @return the block starting at the specified index, if it exists; {@code null} otherwise
+     */
+    public BlockBegin get(int bci) {
+        if (bci < blockMap.length) {
+            return blockMap[bci];
+        }
+        return null;
+    }
+
+    BlockBegin make(int bci) {
+        BlockBegin block = blockMap[bci];
+        if (block == null) {
+            block = new BlockBegin(bci, blockNum++);
+            blockMap[bci] = block;
+        }
+        return block;
+    }
+
+    /**
+     * Gets a conservative approximation of the successors of a given block.
+     * @param block the block for which to get the successors
+     * @return an array of the successors of the specified block
+     */
+    public BlockBegin[] getSuccessors(BlockBegin block) {
+        BlockBegin[] succ = successorMap[block.bci()];
+        return succ == null ? NONE : succ;
+    }
+
+    /**
+     * Gets the exception handlers for a specified block. Note that this
+     * set of exception handlers takes into account whether the block contains
+     * bytecodes that can cause traps or not.
+     * @param block the block for which to get the exception handlers
+     * @return an array of the blocks which represent exception handlers; a zero-length
+     * array of blocks if there are no handlers that cover any potentially trapping
+     * instruction in the specified block
+     */
+    public Collection<BlockBegin> getHandlers(BlockBegin block) {
+        if (exceptionMap == null) {
+            return NONE_LIST;
+        }
+        return exceptionMap.getHandlers(block);
+    }
+
+    /**
+     * Builds the block map and conservative CFG and numbers blocks.
+     * @param computeStoresInLoops {@code true} if the block map builder should
+     * make a second pass over the bytecodes for blocks in loops
+     * @return {@code true} if the block map was built successfully; {@code false} otherwise
+     */
+    public boolean build(boolean computeStoresInLoops) {
+        if (exceptionMap != null) {
+            exceptionMap.setHandlerEntrypoints();
+        }
+        iterateOverBytecodes();
+        moveSuccessorLists();
+        computeBlockNumbers();
+        if (computeStoresInLoops) {
+            // process any blocks in loops to compute their stores
+            // (requires another pass, but produces fewer phi's and ultimately better code)
+            processLoopBlocks();
+        } else {
+            // be conservative and assume all locals are potentially stored in loops
+            // (does not require another pass, but produces more phi's and worse code)
+            storesInLoops.setAll();
+        }
+        return true; // XXX: what bailout conditions should the BlockMap check?
+    }
+
+    /**
+     * Cleans up any internal state not necessary after the initial pass. Note that
+     * this method discards the conservative CFG edges and only retains the block mapping
+     * and stores in loops.
+     */
+    public void cleanup() {
+        // discard internal state no longer needed
+        successorMap = null;
+        loopBlocks = null;
+        exceptionMap = null;
+    }
+
+    /**
+     * Gets the number of blocks in this block map.
+     * @return the number of blocks
+     */
+    public int numberOfBlocks() {
+        return blockNum - firstBlock;
+    }
+
+    public int numberOfBytes() {
+        return code.length;
+    }
+
+    /**
+     * Gets the bitmap that indicates which local variables are assigned in loops.
+     * @return a bitmap which indicates the locals stored in loops
+     */
+    public CiBitMap getStoresInLoops() {
+        return storesInLoops;
+    }
+
+    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)
+        int bci = 0;
+        ExceptionMap exceptionMap = this.exceptionMap;
+        byte[] code = this.code;
+        make(0).setStandardEntry();
+        while (bci < code.length) {
+            int opcode = Bytes.beU1(code, bci);
+            switch (opcode) {
+                case ATHROW:
+                    if (exceptionMap != null) {
+                        exceptionMap.setCanTrap(bci);
+                    }
+                    // fall through
+                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:
+                    if (exceptionMap != null && exceptionMap.isObjectInit) {
+                        exceptionMap.setCanTrap(bci);
+                    }
+                    successorMap[bci] = NONE; // end of control flow
+                    bci += 1; // these are all 1 byte opcodes
+                    break;
+
+                case RET:
+                    successorMap[bci] = NONE; // end of control flow
+                    bci += 2; // ret is 2 bytes
+                    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: {
+                    succ2(bci, bci + 3, bci + Bytes.beS2(code, bci + 1));
+                    bci += 3; // these are all 3 byte opcodes
+                    break;
+                }
+
+                case GOTO: {
+                    succ1(bci, bci + Bytes.beS2(code, bci + 1));
+                    bci += 3; // goto is 3 bytes
+                    break;
+                }
+
+                case GOTO_W: {
+                    succ1(bci, bci + Bytes.beS4(code, bci + 1));
+                    bci += 5; // goto_w is 5 bytes
+                    break;
+                }
+
+                case JSR: {
+                    int target = bci + Bytes.beS2(code, bci + 1);
+                    succ2(bci, bci + 3, target); // make JSR's a successor or not?
+                    addEntrypoint(target, BlockBegin.BlockFlag.SubroutineEntry);
+                    bci += 3; // jsr is 3 bytes
+                    break;
+                }
+
+                case JSR_W: {
+                    int target = bci + Bytes.beS4(code, bci + 1);
+                    succ2(bci, bci + 5, target);
+                    addEntrypoint(target, BlockBegin.BlockFlag.SubroutineEntry);
+                    bci += 5; // jsr_w is 5 bytes
+                    break;
+                }
+
+                case TABLESWITCH: {
+                    BytecodeSwitch sw = new BytecodeTableSwitch(code, bci);
+                    makeSwitchSuccessors(bci, sw);
+                    bci += sw.size();
+                    break;
+                }
+
+                case LOOKUPSWITCH: {
+                    BytecodeSwitch sw = new BytecodeLookupSwitch(code, bci);
+                    makeSwitchSuccessors(bci, sw);
+                    bci += sw.size();
+                    break;
+                }
+                case WIDE: {
+                    bci += lengthOf(code, bci);
+                    break;
+                }
+
+                default: {
+                    if (exceptionMap != null && canTrap(opcode)) {
+                        exceptionMap.setCanTrap(bci);
+                    }
+                    bci += lengthOf(opcode); // all variable length instructions are handled above
+                }
+            }
+        }
+    }
+
+    private void makeSwitchSuccessors(int bci, BytecodeSwitch tswitch) {
+        // make a list of all the successors of a switch
+        int max = tswitch.numberOfCases();
+        ArrayList<BlockBegin> list = new ArrayList<BlockBegin>(max + 1);
+        for (int i = 0; i < max; i++) {
+            list.add(make(tswitch.targetAt(i)));
+        }
+        list.add(make(tswitch.defaultTarget()));
+        successorMap[bci] = list.toArray(new BlockBegin[list.size()]);
+    }
+
+    private void moveSuccessorLists() {
+        // move successor lists from the block-ending bytecodes that created them
+        // to the basic blocks which they end.
+        // also handle fall-through cases from backwards branches into the middle of a block
+        // add exception handlers to basic blocks
+        BlockBegin current = get(0);
+        ExceptionMap exceptionMap = this.exceptionMap;
+        for (int bci = 0; bci < blockMap.length; bci++) {
+            BlockBegin next = blockMap[bci];
+            if (next != null && next != current) {
+                if (current != null) {
+                    // add fall through successor to current block
+                    successorMap[current.bci()] = new BlockBegin[] {next};
+                }
+                current = next;
+            }
+            if (exceptionMap != null) {
+                exceptionMap.addHandlers(current, bci);
+            }
+            BlockBegin[] succ = successorMap[bci];
+            if (succ != null && current != null) {
+                // move this successor list to current block
+                successorMap[bci] = null;
+                successorMap[current.bci()] = succ;
+                current = null;
+            }
+        }
+        assert current == null : "fell off end of code, should end with successor list";
+    }
+
+    private void computeBlockNumbers() {
+        // compute the block number for all blocks
+        int blockNum = this.blockNum;
+        int numBlocks = blockNum - firstBlock;
+        numberBlock(get(0), new CiBitMap(numBlocks), new CiBitMap(numBlocks));
+        this.blockNum = blockNum; // _blockNum is used to compute the number of blocks later
+    }
+
+    private boolean numberBlock(BlockBegin block, CiBitMap visited, CiBitMap active) {
+        // number a block with its reverse post-order traversal number
+        int blockIndex = block.blockID - firstBlock;
+
+        if (visited.get(blockIndex)) {
+            if (active.get(blockIndex)) {
+                // reached block via backward branch
+                block.setParserLoopHeader(true);
+                addLoopBlock(block);
+                return true;
+            }
+            // return whether the block is already a loop header
+            return block.isParserLoopHeader();
+        }
+
+        visited.set(blockIndex);
+        active.set(blockIndex);
+
+        boolean inLoop = false;
+        for (BlockBegin succ : getSuccessors(block)) {
+            // recursively process successors
+            inLoop |= numberBlock(succ, visited, active);
+        }
+        if (exceptionMap != null) {
+            for (BlockBegin succ : exceptionMap.getHandlers(block)) {
+                // process exception handler blocks
+                inLoop |= numberBlock(succ, visited, active);
+            }
+        }
+        // clear active bit after successors are processed
+        active.clear(blockIndex);
+        block.setDepthFirstNumber(blockNum--);
+        if (inLoop) {
+            addLoopBlock(block);
+        }
+
+        return inLoop;
+    }
+
+    private void addLoopBlock(BlockBegin block) {
+        if (loopBlocks == null) {
+            loopBlocks = new ArrayList<BlockBegin>();
+        }
+        loopBlocks.add(block);
+    }
+
+    private void processLoopBlocks() {
+        if (loopBlocks == null) {
+            return;
+        }
+        for (BlockBegin block : loopBlocks) {
+            // process all the stores in this block
+            int bci = block.bci();
+            byte[] code = this.code;
+            while (true) {
+                // iterate over the bytecodes in this block
+                int opcode = code[bci] & 0xff;
+                if (opcode == WIDE) {
+                    bci += processWideStore(code[bci + 1] & 0xff, code, bci);
+                } else if (isStore(opcode)) {
+                    bci += processStore(opcode, code, bci);
+                } else {
+                    bci += lengthOf(code, bci);
+                }
+                if (bci >= code.length || blockMap[bci] != null) {
+                    // stop when we reach the next block
+                    break;
+                }
+            }
+        }
+    }
+
+    private int processWideStore(int opcode, byte[] code, int bci) {
+        switch (opcode) {
+            case IINC:     storeOne(Bytes.beU2(code, bci + 2)); return 6;
+            case ISTORE:   storeOne(Bytes.beU2(code, bci + 2)); return 3;
+            case LSTORE:   storeTwo(Bytes.beU2(code, bci + 2)); return 3;
+            case FSTORE:   storeOne(Bytes.beU2(code, bci + 2)); return 3;
+            case DSTORE:   storeTwo(Bytes.beU2(code, bci + 2)); return 3;
+            case ASTORE:   storeOne(Bytes.beU2(code, bci + 2)); return 3;
+        }
+        return lengthOf(code, bci);
+    }
+
+    private int processStore(int opcode, byte[] code, int bci) {
+        switch (opcode) {
+            case IINC:     storeOne(code[bci + 1] & 0xff); return 3;
+            case ISTORE:   storeOne(code[bci + 1] & 0xff); return 2;
+            case LSTORE:   storeTwo(code[bci + 1] & 0xff); return 2;
+            case FSTORE:   storeOne(code[bci + 1] & 0xff); return 2;
+            case DSTORE:   storeTwo(code[bci + 1] & 0xff); return 2;
+            case WSTORE:
+            case ASTORE:   storeOne(code[bci + 1] & 0xff); return 2;
+            case ISTORE_0: // fall through
+            case ISTORE_1: // fall through
+            case ISTORE_2: // fall through
+            case ISTORE_3: storeOne(opcode - ISTORE_0); return 1;
+            case LSTORE_0: // fall through
+            case LSTORE_1: // fall through
+            case LSTORE_2: // fall through
+            case LSTORE_3: storeTwo(opcode - LSTORE_0); return 1;
+            case FSTORE_0: // fall through
+            case FSTORE_1: // fall through
+            case FSTORE_2: // fall through
+            case FSTORE_3: storeOne(opcode - FSTORE_0); return 1;
+            case DSTORE_0: // fall through
+            case DSTORE_1: // fall through
+            case DSTORE_2: // fall through
+            case DSTORE_3: storeTwo(opcode - DSTORE_0); return 1;
+            case ASTORE_0: // fall through
+            case ASTORE_1: // fall through
+            case ASTORE_2: // fall through
+            case ASTORE_3: storeOne(opcode - ASTORE_0); return 1;
+            case WSTORE_0: // fall through
+            case WSTORE_1: // fall through
+            case WSTORE_2: // fall through
+            case WSTORE_3: storeOne(opcode - WSTORE_0); return 1;
+        }
+        throw Util.shouldNotReachHere();
+    }
+
+    private void storeOne(int local) {
+        storesInLoops.set(local);
+    }
+
+    private void storeTwo(int local) {
+        storesInLoops.set(local);
+        storesInLoops.set(local + 1);
+    }
+
+    private void succ2(int bci, int s1, int s2) {
+        successorMap[bci] = new BlockBegin[] {make(s1), make(s2)};
+    }
+
+    private void succ1(int bci, int s1) {
+        successorMap[bci] = new BlockBegin[] {make(s1)};
+    }
+
+    private static StringBuilder append(StringBuilder sb, BlockBegin block) {
+        return sb.append('B').append(block.blockID).append('@').append(block.bci());
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        for (int bci = 0; bci < blockMap.length; ++bci) {
+            BlockBegin block = blockMap[bci];
+            if (block != null) {
+                append(sb, block);
+                if (loopBlocks != null && loopBlocks.contains(block)) {
+                    sb.append("{loop-header}");
+                }
+                if (successorMap != null) {
+                    BlockBegin[] succs = successorMap[bci];
+                    if (succs != null && succs.length > 0) {
+                        sb.append(" ->");
+                        for (BlockBegin succ : succs) {
+                            append(sb.append(' '), succ);
+                        }
+                    }
+                }
+                Collection<BlockBegin> handlers = getHandlers(block);
+                if (!handlers.isEmpty()) {
+                    sb.append(" xhandlers{");
+                    for (BlockBegin h : handlers) {
+                        append(sb, h).append(' ');
+                    }
+                    sb.append('}');
+                }
+                sb.append(String.format("%n"));
+            }
+        }
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/graph/BlockUtil.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,46 @@
+/*
+ * 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.sun.c1x.graph;
+
+import com.sun.c1x.ir.*;
+
+/**
+ * The {@code BlockUtil} class contains a number of utilities for manipulating a CFG of basic blocks.
+ *
+ * @author Ben L. Titzer
+ */
+public class BlockUtil {
+
+    /**
+     * Disconnects the specified block from all other blocks.
+     * @param block the block to remove from the graph
+     */
+    public static void disconnectFromGraph(BlockBegin block) {
+        for (BlockBegin p : block.predecessors()) {
+            p.end().successors().remove(block);
+        }
+        for (BlockBegin s : block.end().successors()) {
+            s.predecessors().remove(block);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/graph/CriticalEdgeFinder.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,84 @@
+/*
+ * 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.sun.c1x.graph;
+
+import java.util.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.debug.*;
+import com.sun.c1x.ir.*;
+
+/**
+ * This class finds and splits "critical" edges in the control flow graph.
+ * An edge between two blocks {@code A} and {@code B} is "critical" if {@code A}
+ * has more than one successor and {@code B} has more than one predecessor. Such
+ * edges are split by adding a block between the two blocks.
+ *
+ * @author Thomas Wuerthinger
+ */
+public class CriticalEdgeFinder implements BlockClosure {
+
+    private final IR ir;
+
+    /**
+     * The graph edges represented as a map from source to target nodes.
+     * Using a linked hash map makes compilation tracing more deterministic and thus eases debugging.
+     */
+    private Map<BlockBegin, Set<BlockBegin>> edges = C1XOptions.DetailedAsserts ?
+                    new LinkedHashMap<BlockBegin, Set<BlockBegin>>() :
+                    new HashMap<BlockBegin, Set<BlockBegin>>();
+
+    public CriticalEdgeFinder(IR ir) {
+        this.ir = ir;
+    }
+
+    public void apply(BlockBegin block) {
+        if (block.numberOfSux() >= 2) {
+            for (BlockBegin succ : block.end().successors()) {
+                if (succ.numberOfPreds() >= 2) {
+                    // TODO: (tw) probably we don't have to make it a critical edge if succ only contains the _same_ predecessor multiple times.
+                    recordCriticalEdge(block, succ);
+                }
+            }
+        }
+    }
+
+    private void recordCriticalEdge(BlockBegin block, BlockBegin succ) {
+        if (!edges.containsKey(block)) {
+            edges.put(block, new HashSet<BlockBegin>());
+        }
+
+        edges.get(block).add(succ);
+    }
+
+    public void splitCriticalEdges() {
+        for (BlockBegin from : edges.keySet()) {
+            for (BlockBegin to : edges.get(from)) {
+                BlockBegin split = ir.splitEdge(from, to);
+                if (C1XOptions.PrintHIR) {
+                    TTY.println("Split edge between block %d and block %d, creating new block %d", from.blockID, to.blockID, split.blockID);
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/graph/GraphBuilder.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,2917 @@
+/*
+ * 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.sun.c1x.graph;
+
+import static com.sun.cri.bytecode.Bytecodes.*;
+import static java.lang.reflect.Modifier.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.debug.*;
+import com.sun.c1x.graph.ScopeData.ReturnBlock;
+import com.sun.c1x.ir.*;
+import com.sun.c1x.ir.Value.Flag;
+import com.sun.c1x.opt.*;
+import com.sun.c1x.util.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.bytecode.Bytecodes.JniOp;
+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.
+ *
+ * @author Ben L. Titzer
+ * @author Doug Simon
+ */
+public final class GraphBuilder {
+
+    /**
+     * The minimum value to which {@link C1XOptions#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 C1XOptions#TraceBytecodeParserLevel} must be set to trace
+     * the frame state before each bytecode instruction as it is parsed.
+     */
+    public static final int TRACELEVEL_STATE = 2;
+
+    final IR ir;
+    final C1XCompilation compilation;
+    final CiStatistics stats;
+
+    /**
+     * Map used to implement local value numbering for the current block.
+     */
+    final ValueMap localValueMap;
+
+    /**
+     * Map used for local load elimination (i.e. within the current block).
+     */
+    final MemoryMap memoryMap;
+
+    final Canonicalizer canonicalizer;     // canonicalizer which does strength reduction + constant folding
+    ScopeData scopeData;                   // Per-scope data; used for inlining
+    BlockBegin curBlock;                   // the current block
+    MutableFrameState curState;            // the current execution state
+    Instruction lastInstr;                 // the last instruction added
+    final LogStream log;
+
+    boolean skipBlock;                     // skip processing of the rest of this block
+    private Value rootMethodSynchronizedObject;
+
+    /**
+     * Creates a new, initialized, {@code GraphBuilder} instance for a given compilation.
+     *
+     * @param compilation the compilation
+     * @param ir the IR to build the graph into
+     */
+    public GraphBuilder(C1XCompilation compilation, IR ir) {
+        this.compilation = compilation;
+        this.ir = ir;
+        this.stats = compilation.stats;
+        this.memoryMap = C1XOptions.OptLocalLoadElimination ? new MemoryMap() : null;
+        this.localValueMap = C1XOptions.OptLocalValueNumbering ? new ValueMap() : null;
+        this.canonicalizer = C1XOptions.OptCanonicalize ? new Canonicalizer(compilation.runtime, compilation.method, compilation.target) : null;
+        log = C1XOptions.TraceBytecodeParserLevel > 0 ? new LogStream(TTY.out()) : null;
+    }
+
+    /**
+     * Builds the graph for a the specified {@code IRScope}.
+     * @param scope the top IRScope
+     */
+    public void build(IRScope scope) {
+        RiMethod rootMethod = compilation.method;
+
+        if (log != null) {
+            log.println();
+            log.println("Compiling " + compilation.method);
+        }
+
+        // 1. create the start block
+        ir.startBlock = new BlockBegin(0, ir.nextBlockNumber());
+        BlockBegin startBlock = ir.startBlock;
+
+        // 2. compute the block map and get the entrypoint(s)
+        BlockMap blockMap = compilation.getBlockMap(scope.method, compilation.osrBCI);
+        BlockBegin stdEntry = blockMap.get(0);
+        BlockBegin osrEntry = compilation.osrBCI < 0 ? null : blockMap.get(compilation.osrBCI);
+        pushRootScope(scope, blockMap, startBlock);
+        MutableFrameState initialState = stateAtEntry(rootMethod);
+        startBlock.mergeOrClone(initialState);
+        BlockBegin syncHandler = null;
+
+        // 3. setup internal state for appending instructions
+        curBlock = startBlock;
+        lastInstr = startBlock;
+        lastInstr.setNext(null, -1);
+        curState = initialState;
+
+        if (isSynchronized(rootMethod.accessFlags())) {
+            // 4A.1 add a monitor enter to the start block
+            rootMethodSynchronizedObject = synchronizedObject(initialState, compilation.method);
+            genMonitorEnter(rootMethodSynchronizedObject, Instruction.SYNCHRONIZATION_ENTRY_BCI);
+            // 4A.2 finish the start block
+            finishStartBlock(startBlock, stdEntry, osrEntry);
+
+            // 4A.3 setup an exception handler to unlock the root method synchronized object
+            syncHandler = new BlockBegin(Instruction.SYNCHRONIZATION_ENTRY_BCI, ir.nextBlockNumber());
+            syncHandler.setExceptionEntry();
+            syncHandler.setBlockFlag(BlockBegin.BlockFlag.IsOnWorkList);
+            syncHandler.setBlockFlag(BlockBegin.BlockFlag.DefaultExceptionHandler);
+
+            ExceptionHandler h = new ExceptionHandler(new CiExceptionHandler(0, rootMethod.code().length, -1, 0, null));
+            h.setEntryBlock(syncHandler);
+            scopeData.addExceptionHandler(h);
+        } else {
+            // 4B.1 simply finish the start block
+            finishStartBlock(startBlock, stdEntry, osrEntry);
+        }
+
+        // 5.
+        C1XIntrinsic intrinsic = C1XOptions.OptIntrinsify ? C1XIntrinsic.getIntrinsic(rootMethod) : null;
+        if (intrinsic != null) {
+            lastInstr = stdEntry;
+            // 6A.1 the root method is an intrinsic; load the parameters onto the stack and try to inline it
+            if (C1XOptions.OptIntrinsify && osrEntry == null) {
+                // try to inline an Intrinsic node
+                boolean isStatic = Modifier.isStatic(rootMethod.accessFlags());
+                int argsSize = rootMethod.signature().argumentSlots(!isStatic);
+                Value[] args = new Value[argsSize];
+                for (int i = 0; i < args.length; i++) {
+                    args[i] = curState.localAt(i);
+                }
+                if (tryInlineIntrinsic(rootMethod, args, isStatic, intrinsic)) {
+                    // intrinsic inlining succeeded, add the return node
+                    CiKind rt = returnKind(rootMethod).stackKind();
+                    Value result = null;
+                    if (rt != CiKind.Void) {
+                        result = pop(rt);
+                    }
+                    genReturn(result);
+                    BlockEnd end = (BlockEnd) lastInstr;
+                    stdEntry.setEnd(end);
+                    end.setStateAfter(curState.immutableCopy(bci()));
+                }  else {
+                    // try intrinsic failed; do the normal parsing
+                    scopeData.addToWorkList(stdEntry);
+                    iterateAllBlocks();
+                }
+            } else {
+                // 6B.1 do the normal parsing
+                scopeData.addToWorkList(stdEntry);
+                iterateAllBlocks();
+            }
+        } else {
+            RiType accessor = openAccessorScope(rootMethod);
+
+            // 6B.1 do the normal parsing
+            scopeData.addToWorkList(stdEntry);
+            iterateAllBlocks();
+
+            closeAccessorScope(accessor);
+        }
+
+        if (syncHandler != null && syncHandler.stateBefore() != null) {
+            // generate unlocking code if the exception handler is reachable
+            fillSyncHandler(rootMethodSynchronizedObject, syncHandler, false);
+        }
+
+        if (compilation.osrBCI >= 0) {
+            BlockBegin osrBlock = blockMap.get(compilation.osrBCI);
+            assert osrBlock.wasVisited();
+            if (!osrBlock.stateBefore().stackEmpty()) {
+                throw new CiBailout("cannot OSR with non-empty stack");
+            }
+        }
+    }
+
+    private void closeAccessorScope(RiType accessor) {
+        if (accessor != null) {
+            boundAccessor.set(null);
+        }
+    }
+
+    private RiType openAccessorScope(RiMethod rootMethod) {
+        RiType accessor = rootMethod.accessor();
+        if (accessor != null) {
+            assert boundAccessor.get() == null;
+            boundAccessor.set(accessor);
+
+            // What looks like an object receiver in the bytecode may not be a word value
+            compilation.setNotTypesafe();
+        }
+        return accessor;
+    }
+
+    private void finishStartBlock(BlockBegin startBlock, BlockBegin stdEntry, BlockBegin osrEntry) {
+        assert curBlock == startBlock;
+        Base base = new Base(stdEntry, osrEntry);
+        appendWithoutOptimization(base, 0);
+        FrameState stateAfter = curState.immutableCopy(bci());
+        base.setStateAfter(stateAfter);
+        startBlock.setEnd(base);
+        assert stdEntry.stateBefore() == null;
+        stdEntry.mergeOrClone(stateAfter);
+    }
+
+    void pushRootScope(IRScope scope, BlockMap blockMap, BlockBegin start) {
+        BytecodeStream stream = new BytecodeStream(scope.method.code());
+        RiConstantPool constantPool = compilation.runtime.getConstantPool(scope.method);
+        scopeData = new ScopeData(null, scope, blockMap, stream, constantPool);
+        curBlock = start;
+    }
+
+    public boolean hasHandler() {
+        return scopeData.hasHandler();
+    }
+
+    public IRScope scope() {
+        return scopeData.scope;
+    }
+
+    public IRScope rootScope() {
+        IRScope root = scope();
+        while (root.caller != null) {
+            root = root.caller;
+        }
+        return root;
+    }
+
+    public RiMethod method() {
+        return scopeData.scope.method;
+    }
+
+    public BytecodeStream stream() {
+        return scopeData.stream;
+    }
+
+    public int bci() {
+        return scopeData.stream.currentBCI();
+    }
+
+    public int nextBCI() {
+        return scopeData.stream.nextBCI();
+    }
+
+    private void ipush(Value x) {
+        curState.ipush(x);
+    }
+
+    private void lpush(Value x) {
+        curState.lpush(x);
+    }
+
+    private void fpush(Value x) {
+        curState.fpush(x);
+    }
+
+    private void dpush(Value x) {
+        curState.dpush(x);
+    }
+
+    private void apush(Value x) {
+        curState.apush(x);
+    }
+
+    private void wpush(Value x) {
+        curState.wpush(x);
+    }
+
+    private void push(CiKind kind, Value x) {
+        curState.push(kind, x);
+    }
+
+    private void pushReturn(CiKind kind, Value x) {
+        if (kind != CiKind.Void) {
+            curState.push(kind.stackKind(), x);
+        }
+    }
+
+    private Value ipop() {
+        return curState.ipop();
+    }
+
+    private Value lpop() {
+        return curState.lpop();
+    }
+
+    private Value fpop() {
+        return curState.fpop();
+    }
+
+    private Value dpop() {
+        return curState.dpop();
+    }
+
+    private Value apop() {
+        return curState.apop();
+    }
+
+    private Value wpop() {
+        return curState.wpop();
+    }
+
+    private Value pop(CiKind kind) {
+        return curState.pop(kind);
+    }
+
+    private CiKind peekKind() {
+        Value top = curState.stackAt(curState.stackSize() - 1);
+        if (top == null) {
+            top = curState.stackAt(curState.stackSize() - 2);
+            assert top != null;
+            assert top.kind.isDoubleWord();
+        }
+        return top.kind;
+    }
+
+    private void loadLocal(int index, CiKind kind) {
+        push(kind, curState.loadLocal(index));
+    }
+
+    private void storeLocal(CiKind kind, int index) {
+        if (scopeData.parsingJsr()) {
+            // We need to do additional tracking of the location of the return
+            // address for jsrs since we don't handle arbitrary jsr/ret
+            // constructs. Here we are figuring out in which circumstances we
+            // need to bail out.
+            if (kind == CiKind.Object) {
+                // might be storing the JSR return address
+                Value x = curState.xpop();
+                if (x.kind.isJsr()) {
+                    setJsrReturnAddressLocal(index);
+                    curState.storeLocal(index, x);
+                } else {
+                    // nope, not storing the JSR return address
+                    assert x.kind.isObject();
+                    curState.storeLocal(index, x);
+                    overwriteJsrReturnAddressLocal(index);
+                }
+                return;
+            } else {
+                // not storing the JSR return address local, but might overwrite it
+                overwriteJsrReturnAddressLocal(index);
+            }
+        }
+
+        curState.storeLocal(index, pop(kind));
+    }
+
+    private void overwriteJsrReturnAddressLocal(int index) {
+        if (index == scopeData.jsrEntryReturnAddressLocal()) {
+            scopeData.setJsrEntryReturnAddressLocal(-1);
+        }
+    }
+
+    private void setJsrReturnAddressLocal(int index) {
+        scopeData.setJsrEntryReturnAddressLocal(index);
+
+        // Also check parent jsrs (if any) at this time to see whether
+        // they are using this local. We don't handle skipping over a
+        // ret.
+        for (ScopeData cur = scopeData.parent; cur != null && cur.parsingJsr() && cur.scope == scope(); cur = cur.parent) {
+            if (cur.jsrEntryReturnAddressLocal() == index) {
+                throw new CiBailout("subroutine overwrites return address from previous subroutine");
+            }
+        }
+    }
+
+    List<ExceptionHandler> handleException(Instruction x, int bci) {
+        if (!hasHandler()) {
+            return Util.uncheckedCast(Collections.EMPTY_LIST);
+        }
+
+        ArrayList<ExceptionHandler> exceptionHandlers = new ArrayList<ExceptionHandler>();
+        ScopeData curScopeData = scopeData;
+        FrameState stateBefore = x.stateBefore();
+        int scopeCount = 0;
+
+        assert stateBefore != null : "exception handler state must be available for " + x;
+        FrameState state = stateBefore;
+        do {
+            assert curScopeData.scope == state.scope() : "scopes do not match";
+            assert bci == Instruction.SYNCHRONIZATION_ENTRY_BCI || bci == curScopeData.stream.currentBCI() : "invalid bci";
+
+            // join with all potential exception handlers
+            List<ExceptionHandler> handlers = curScopeData.exceptionHandlers();
+            if (handlers != null) {
+                for (ExceptionHandler handler : handlers) {
+                    if (handler.covers(bci)) {
+                        // if the handler covers this bytecode index, add it to the list
+                        if (addExceptionHandler(exceptionHandlers, handler, curScopeData, state, scopeCount)) {
+                            // if the handler was a default handler, we are done
+                            return exceptionHandlers;
+                        }
+                    }
+                }
+            }
+            // pop the scope to the next IRScope level
+            // if parsing a JSR, skip scopes until the next IRScope level
+            IRScope curScope = curScopeData.scope;
+            while (curScopeData.parent != null && curScopeData.parent.scope == curScope) {
+                curScopeData = curScopeData.parent;
+            }
+            if (curScopeData.parent == null) {
+                // no more levels, done
+                break;
+            }
+            // there is another level, pop
+            state = state.callerState();
+            bci = curScopeData.scope.callerBCI();
+            curScopeData = curScopeData.parent;
+            scopeCount++;
+
+        } while (true);
+
+        return exceptionHandlers;
+    }
+
+    /**
+     * Adds an exception handler to the {@linkplain BlockBegin#exceptionHandlerBlocks() list}
+     * of exception handlers for the {@link #curBlock current block}.
+     *
+     * @param exceptionHandlers
+     * @param handler
+     * @param curScopeData
+     * @param curState the current state with empty stack
+     * @param scopeCount
+     * @return {@code true} if handler catches all exceptions (i.e. {@code handler.isCatchAll() == true})
+     */
+    private boolean addExceptionHandler(ArrayList<ExceptionHandler> exceptionHandlers, ExceptionHandler handler, ScopeData curScopeData, FrameState curState, int scopeCount) {
+        compilation.setHasExceptionHandlers();
+
+        BlockBegin entry = handler.entryBlock();
+        FrameState entryState = entry.stateBefore();
+
+        assert entry.bci() == handler.handler.handlerBCI();
+        assert entry.bci() == -1 || entry == curScopeData.blockAt(entry.bci()) : "blocks must correspond";
+        assert entryState == null || curState.locksSize() == entryState.locksSize() : "locks do not match";
+
+        // exception handler starts with an empty expression stack
+        curState = curState.immutableCopyWithEmptyStack();
+
+        entry.mergeOrClone(curState);
+
+        // add current state for correct handling of phi functions
+        int phiOperand = entry.addExceptionState(curState);
+
+        // add entry to the list of exception handlers of this block
+        curBlock.addExceptionHandler(entry);
+
+        // add back-edge from exception handler entry to this block
+        if (!entry.predecessors().contains(curBlock)) {
+            entry.addPredecessor(curBlock);
+        }
+
+        // clone exception handler
+        ExceptionHandler newHandler = new ExceptionHandler(handler);
+        newHandler.setPhiOperand(phiOperand);
+        newHandler.setScopeCount(scopeCount);
+        exceptionHandlers.add(newHandler);
+
+        // fill in exception handler subgraph lazily
+        if (!entry.wasVisited()) {
+            curScopeData.addToWorkList(entry);
+        } else {
+            // This will occur for exception handlers that cover themselves. This code
+            // pattern is generated by javac for synchronized blocks. See the following
+            // for why this change to javac was made:
+            //
+            //   http://www.cs.arizona.edu/projects/sumatra/hallofshame/java-async-race.html
+        }
+
+        // stop when reaching catch all
+        return handler.isCatchAll();
+    }
+
+    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() || C1XOptions.TestPatching) {
+                push(CiKind.Object, append(new ResolveClass(riType, RiType.Representation.JavaClass, null)));
+            } else {
+                push(CiKind.Object, append(new Constant(riType.getEncoding(Representation.JavaClass))));
+            }
+        } else if (con instanceof CiConstant) {
+            CiConstant constant = (CiConstant) con;
+            push(constant.kind.stackKind(), appendConstant(constant));
+        } else {
+            throw new Error("lookupConstant returned an object of incorrect type");
+        }
+    }
+
+    void genLoadIndexed(CiKind kind) {
+        FrameState stateBefore = curState.immutableCopy(bci());
+        Value index = ipop();
+        Value array = apop();
+        Value length = null;
+        if (cseArrayLength(array)) {
+            length = append(new ArrayLength(array, stateBefore));
+        }
+        Value v = append(new LoadIndexed(array, index, length, kind, stateBefore));
+        push(kind.stackKind(), v);
+    }
+
+    void genStoreIndexed(CiKind kind) {
+        FrameState stateBefore = curState.immutableCopy(bci());
+        Value value = pop(kind.stackKind());
+        Value index = ipop();
+        Value array = apop();
+        Value length = null;
+        if (cseArrayLength(array)) {
+            length = append(new ArrayLength(array, stateBefore));
+        }
+        StoreIndexed result = new StoreIndexed(array, index, length, kind, value, stateBefore);
+        append(result);
+        if (memoryMap != null) {
+            memoryMap.storeValue(value);
+        }
+    }
+
+    void stackOp(int opcode) {
+        switch (opcode) {
+            case POP: {
+                curState.xpop();
+                break;
+            }
+            case POP2: {
+                curState.xpop();
+                curState.xpop();
+                break;
+            }
+            case DUP: {
+                Value w = curState.xpop();
+                curState.xpush(w);
+                curState.xpush(w);
+                break;
+            }
+            case DUP_X1: {
+                Value w1 = curState.xpop();
+                Value w2 = curState.xpop();
+                curState.xpush(w1);
+                curState.xpush(w2);
+                curState.xpush(w1);
+                break;
+            }
+            case DUP_X2: {
+                Value w1 = curState.xpop();
+                Value w2 = curState.xpop();
+                Value w3 = curState.xpop();
+                curState.xpush(w1);
+                curState.xpush(w3);
+                curState.xpush(w2);
+                curState.xpush(w1);
+                break;
+            }
+            case DUP2: {
+                Value w1 = curState.xpop();
+                Value w2 = curState.xpop();
+                curState.xpush(w2);
+                curState.xpush(w1);
+                curState.xpush(w2);
+                curState.xpush(w1);
+                break;
+            }
+            case DUP2_X1: {
+                Value w1 = curState.xpop();
+                Value w2 = curState.xpop();
+                Value w3 = curState.xpop();
+                curState.xpush(w2);
+                curState.xpush(w1);
+                curState.xpush(w3);
+                curState.xpush(w2);
+                curState.xpush(w1);
+                break;
+            }
+            case DUP2_X2: {
+                Value w1 = curState.xpop();
+                Value w2 = curState.xpop();
+                Value w3 = curState.xpop();
+                Value w4 = curState.xpop();
+                curState.xpush(w2);
+                curState.xpush(w1);
+                curState.xpush(w4);
+                curState.xpush(w3);
+                curState.xpush(w2);
+                curState.xpush(w1);
+                break;
+            }
+            case SWAP: {
+                Value w1 = curState.xpop();
+                Value w2 = curState.xpop();
+                curState.xpush(w1);
+                curState.xpush(w2);
+                break;
+            }
+            default:
+                throw Util.shouldNotReachHere();
+        }
+
+    }
+
+    void genArithmeticOp(CiKind kind, int opcode) {
+        genArithmeticOp(kind, opcode, null);
+    }
+
+    void genArithmeticOp(CiKind kind, int opcode, FrameState state) {
+        genArithmeticOp(kind, opcode, kind, kind, state);
+    }
+
+    void genArithmeticOp(CiKind result, int opcode, CiKind x, CiKind y, FrameState state) {
+        Value yValue = pop(y);
+        Value xValue = pop(x);
+        Value result1 = append(new ArithmeticOp(opcode, result, xValue, yValue, isStrict(method().accessFlags()), state));
+        push(result, result1);
+    }
+
+    void genNegateOp(CiKind kind) {
+        push(kind, append(new NegateOp(pop(kind))));
+    }
+
+    void genShiftOp(CiKind kind, int opcode) {
+        Value s = ipop();
+        Value x = pop(kind);
+        // note that strength reduction of e << K >>> K is correctly handled in canonicalizer now
+        push(kind, append(new ShiftOp(opcode, x, s)));
+    }
+
+    void genLogicOp(CiKind kind, int opcode) {
+        Value y = pop(kind);
+        Value x = pop(kind);
+        push(kind, append(new LogicOp(opcode, x, y)));
+    }
+
+    void genCompareOp(CiKind kind, int opcode, CiKind resultKind) {
+        Value y = pop(kind);
+        Value x = pop(kind);
+        Value value = append(new CompareOp(opcode, resultKind, x, y));
+        if (!resultKind.isVoid()) {
+            ipush(value);
+        }
+    }
+
+    void genUnsignedCompareOp(CiKind kind, int opcode, int op) {
+        Value y = pop(kind);
+        Value x = pop(kind);
+        ipush(append(new UnsignedCompareOp(opcode, op, x, y)));
+    }
+
+    void genConvert(int opcode, CiKind from, CiKind to) {
+        CiKind tt = to.stackKind();
+        push(tt, append(new Convert(opcode, pop(from.stackKind()), tt)));
+    }
+
+    void genIncrement() {
+        int index = stream().readLocalIndex();
+        int delta = stream().readIncrement();
+        Value x = curState.localAt(index);
+        Value y = append(Constant.forInt(delta));
+        curState.storeLocal(index, append(new ArithmeticOp(IADD, CiKind.Int, x, y, isStrict(method().accessFlags()), null)));
+    }
+
+    void genGoto(int fromBCI, int toBCI) {
+        boolean isSafepoint = !scopeData.noSafepoints() && toBCI <= fromBCI;
+        append(new Goto(blockAt(toBCI), null, isSafepoint));
+    }
+
+    void ifNode(Value x, Condition cond, Value y, FrameState stateBefore) {
+        BlockBegin tsucc = blockAt(stream().readBranchDest());
+        BlockBegin fsucc = blockAt(stream().nextBCI());
+        int bci = stream().currentBCI();
+        boolean isSafepoint = !scopeData.noSafepoints() && tsucc.bci() <= bci || fsucc.bci() <= bci;
+        append(new If(x, cond, false, y, tsucc, fsucc, isSafepoint ? stateBefore : null, isSafepoint));
+    }
+
+    void genIfZero(Condition cond) {
+        Value y = appendConstant(CiConstant.INT_0);
+        FrameState stateBefore = curState.immutableCopy(bci());
+        Value x = ipop();
+        ifNode(x, cond, y, stateBefore);
+    }
+
+    void genIfNull(Condition cond) {
+        FrameState stateBefore = curState.immutableCopy(bci());
+        Value y = appendConstant(CiConstant.NULL_OBJECT);
+        Value x = apop();
+        ifNode(x, cond, y, stateBefore);
+    }
+
+    void genIfSame(CiKind kind, Condition cond) {
+        FrameState stateBefore = curState.immutableCopy(bci());
+        Value y = pop(kind);
+        Value x = pop(kind);
+        ifNode(x, cond, y, stateBefore);
+    }
+
+    void genThrow(int bci) {
+        FrameState stateBefore = curState.immutableCopy(bci());
+        Throw t = new Throw(apop(), stateBefore, !scopeData.noSafepoints());
+        appendWithoutOptimization(t, bci);
+    }
+
+    void genUnsafeCast(RiMethod method) {
+        compilation.setNotTypesafe();
+        RiSignature signature = method.signature();
+        int argCount = signature.argumentCount(false);
+        RiType accessingClass = scope().method.holder();
+        RiType fromType;
+        RiType toType = signature.returnType(accessingClass);
+        if (argCount == 1) {
+            fromType = signature.argumentTypeAt(0, accessingClass);
+        } else {
+            assert argCount == 0 : "method with @UNSAFE_CAST must have exactly 1 argument";
+            fromType = method.holder();
+        }
+        CiKind from = fromType.kind();
+        CiKind to = toType.kind();
+        boolean redundant = compilation.archKindsEqual(to, from);
+        curState.push(to, append(new UnsafeCast(toType, curState.pop(from), redundant)));
+    }
+
+    void genCheckCast() {
+        int cpi = stream().readCPI();
+        RiType type = constantPool().lookupType(cpi, CHECKCAST);
+        boolean isInitialized = !C1XOptions.TestPatching && type.isResolved() && type.isInitialized();
+        Value typeInstruction = genResolveClass(RiType.Representation.ObjectHub, type, isInitialized, cpi);
+        CheckCast c = new CheckCast(type, typeInstruction, apop(), null);
+        apush(append(c));
+        checkForDirectCompare(c);
+    }
+
+    void genInstanceOf() {
+        int cpi = stream().readCPI();
+        RiType type = constantPool().lookupType(cpi, INSTANCEOF);
+        boolean isInitialized = !C1XOptions.TestPatching && type.isResolved() && type.isInitialized();
+        Value typeInstruction = genResolveClass(RiType.Representation.ObjectHub, type, isInitialized, cpi);
+        InstanceOf i = new InstanceOf(type, typeInstruction, apop(), null);
+        ipush(append(i));
+        checkForDirectCompare(i);
+    }
+
+    private void checkForDirectCompare(TypeCheck check) {
+        RiType type = check.targetClass();
+        if (!type.isResolved() || type.isArrayClass()) {
+            return;
+        }
+        if (assumeLeafClass(type)) {
+            check.setDirectCompare();
+        }
+    }
+
+    void genNewInstance(int cpi) {
+        FrameState stateBefore = curState.immutableCopy(bci());
+        RiType type = constantPool().lookupType(cpi, NEW);
+        NewInstance n = new NewInstance(type, cpi, constantPool(), stateBefore);
+        if (memoryMap != null) {
+            memoryMap.newInstance(n);
+        }
+        apush(append(n));
+    }
+
+    void genNewTypeArray(int typeCode) {
+        FrameState stateBefore = curState.immutableCopy(bci());
+        CiKind kind = CiKind.fromArrayTypeCode(typeCode);
+        RiType elementType = compilation.runtime.asRiType(kind);
+        apush(append(new NewTypeArray(ipop(), elementType, stateBefore)));
+    }
+
+    void genNewObjectArray(int cpi) {
+        RiType type = constantPool().lookupType(cpi, ANEWARRAY);
+        FrameState stateBefore = curState.immutableCopy(bci());
+        NewArray n = new NewObjectArray(type, ipop(), stateBefore);
+        apush(append(n));
+    }
+
+    void genNewMultiArray(int cpi) {
+        RiType type = constantPool().lookupType(cpi, MULTIANEWARRAY);
+        FrameState stateBefore = curState.immutableCopy(bci());
+        int rank = stream().readUByte(bci() + 3);
+        Value[] dims = new Value[rank];
+        for (int i = rank - 1; i >= 0; i--) {
+            dims[i] = ipop();
+        }
+        NewArray n = new NewMultiArray(type, dims, stateBefore, cpi, constantPool());
+        apush(append(n));
+    }
+
+    void genGetField(int cpi, RiField field) {
+        // Must copy the state here, because the field holder must still be on the stack.
+        FrameState stateBefore = curState.immutableCopy(bci());
+        boolean isLoaded = !C1XOptions.TestPatching && field.isResolved();
+        LoadField load = new LoadField(apop(), field, false, stateBefore, isLoaded);
+        appendOptimizedLoadField(field.kind(), load);
+    }
+
+    void genPutField(int cpi, RiField field) {
+        // Must copy the state here, because the field holder must still be on the stack.
+        FrameState stateBefore = curState.immutableCopy(bci());
+        boolean isLoaded = !C1XOptions.TestPatching && field.isResolved();
+        Value value = pop(field.kind().stackKind());
+        appendOptimizedStoreField(new StoreField(apop(), field, value, false, stateBefore, isLoaded));
+    }
+
+    void genGetStatic(int cpi, RiField field) {
+        RiType holder = field.holder();
+        boolean isInitialized = !C1XOptions.TestPatching && field.isResolved() && holder.isResolved() && holder.isInitialized();
+        CiConstant constantValue = null;
+        if (isInitialized && C1XOptions.CanonicalizeConstantFields) {
+            constantValue = field.constantValue(null);
+        }
+        if (constantValue != null) {
+            push(constantValue.kind.stackKind(), appendConstant(constantValue));
+        } else {
+            Value container = genResolveClass(RiType.Representation.StaticFields, holder, isInitialized, cpi);
+            LoadField load = new LoadField(container, field, true, null, isInitialized);
+            appendOptimizedLoadField(field.kind(), load);
+        }
+    }
+
+    void genPutStatic(int cpi, RiField field) {
+        RiType holder = field.holder();
+        boolean isInitialized = !C1XOptions.TestPatching && field.isResolved() && holder.isResolved() && holder.isInitialized();
+        Value container = genResolveClass(RiType.Representation.StaticFields, holder, isInitialized, cpi);
+        Value value = pop(field.kind().stackKind());
+        StoreField store = new StoreField(container, field, value, true, null, isInitialized);
+        appendOptimizedStoreField(store);
+    }
+
+    private Value genResolveClass(RiType.Representation representation, RiType holder, boolean initialized, int cpi) {
+        Value holderInstr;
+        if (initialized) {
+            holderInstr = appendConstant(holder.getEncoding(representation));
+        } else {
+            holderInstr = append(new ResolveClass(holder, representation, null));
+        }
+        return holderInstr;
+    }
+
+    private void appendOptimizedStoreField(StoreField store) {
+        if (memoryMap != null) {
+            StoreField previous = memoryMap.store(store);
+            if (previous == null) {
+                // the store is redundant, do not append
+                return;
+            }
+        }
+        append(store);
+    }
+
+    private void appendOptimizedLoadField(CiKind kind, LoadField load) {
+        if (memoryMap != null) {
+            Value replacement = memoryMap.load(load);
+            if (replacement != load) {
+                // the memory buffer found a replacement for this load (no need to append)
+                push(kind.stackKind(), replacement);
+                return;
+            }
+        }
+        // append the load to the instruction
+        Value optimized = append(load);
+        if (memoryMap != null && optimized != load) {
+            // local optimization happened, replace its value in the memory map
+            memoryMap.setResult(load, optimized);
+        }
+        push(kind.stackKind(), optimized);
+    }
+
+    /**
+     * Temporary work-around to support the @ACCESSOR Maxine annotation.
+     */
+    private RiMethod handleInvokeAccessorOrBuiltin(RiMethod target) {
+        target = bindAccessorMethod(target);
+        if (target.intrinsic() != 0) {
+            int intrinsic = target.intrinsic();
+            int opcode = intrinsic & 0xff;
+            switch (opcode) {
+                case PREAD          : genLoadPointer(intrinsic); break;
+                case PGET           : genLoadPointer(intrinsic); break;
+                case PWRITE         : genStorePointer(intrinsic); break;
+                case PSET           : genStorePointer(intrinsic); break;
+                case PCMPSWP        : genCompareAndSwap(intrinsic); break;
+                default:
+                    throw new CiBailout("unknown bytecode " + opcode + " (" + nameOf(opcode) + ")");
+            }
+            return null;
+        }
+        return target;
+    }
+
+    void genInvokeStatic(RiMethod target, int cpi, RiConstantPool constantPool) {
+        target = handleInvokeAccessorOrBuiltin(target);
+        if (target == null) {
+            return;
+        }
+        RiType holder = target.holder();
+        boolean isInitialized = !C1XOptions.TestPatching && target.isResolved() && holder.isInitialized();
+        if (!isInitialized && C1XOptions.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.
+            genResolveClass(RiType.Representation.StaticFields, holder, isInitialized, cpi);
+        }
+
+        Value[] args = curState.popArguments(target.signature().argumentSlots(false));
+        if (!tryRemoveCall(target, args, true)) {
+            if (!tryInline(target, args)) {
+                appendInvoke(INVOKESTATIC, target, args, true, cpi, constantPool);
+            }
+        }
+    }
+
+    void genInvokeInterface(RiMethod target, int cpi, RiConstantPool constantPool) {
+        target = handleInvokeAccessorOrBuiltin(target);
+        if (target == null) {
+            return;
+        }
+        Value[] args = curState.popArguments(target.signature().argumentSlots(true));
+        if (!tryRemoveCall(target, args, false)) {
+            genInvokeIndirect(INVOKEINTERFACE, target, args, cpi, constantPool);
+        }
+    }
+
+    void genInvokeVirtual(RiMethod target, int cpi, RiConstantPool constantPool) {
+        target = handleInvokeAccessorOrBuiltin(target);
+        if (target == null) {
+            return;
+        }
+        Value[] args = curState.popArguments(target.signature().argumentSlots(true));
+        if (!tryRemoveCall(target, args, false)) {
+            genInvokeIndirect(INVOKEVIRTUAL, target, args, cpi, constantPool);
+        }
+    }
+
+    void genInvokeSpecial(RiMethod target, RiType knownHolder, int cpi, RiConstantPool constantPool) {
+        target = handleInvokeAccessorOrBuiltin(target);
+        if (target == null) {
+            return;
+        }
+        Value[] args = curState.popArguments(target.signature().argumentSlots(true));
+        if (!tryRemoveCall(target, args, false)) {
+            invokeDirect(target, args, knownHolder, cpi, constantPool);
+        }
+    }
+
+    /**
+     * Temporary work-around to support the @ACCESSOR Maxine annotation.
+     */
+    private static final Class<?> Accessor;
+    static {
+        Class<?> c = null;
+        try {
+            c = Class.forName("com.sun.max.unsafe.Accessor");
+        } catch (ClassNotFoundException e) {
+        }
+        Accessor = c;
+    }
+
+    /**
+     * Temporary work-around to support the @ACCESSOR Maxine annotation.
+     */
+    private static ThreadLocal<RiType> boundAccessor = new ThreadLocal<RiType>();
+
+    /**
+     * Temporary work-around to support the @ACCESSOR Maxine annotation.
+     */
+    private static RiMethod bindAccessorMethod(RiMethod target) {
+        if (Accessor != null && target.isResolved() && target.holder().javaClass() == Accessor) {
+            RiType accessor = boundAccessor.get();
+            assert accessor != null : "Cannot compile call to method in " + target.holder() + " without enclosing @ACCESSOR annotated method";
+            RiMethod newTarget = accessor.resolveMethodImpl(target);
+            assert target != newTarget : "Could not bind " + target + " to a method in " + accessor;
+            target = newTarget;
+        }
+        return target;
+    }
+
+    /**
+     * Temporary work-around to support the @ACCESSOR Maxine annotation.
+     */
+    private boolean inlineWithBoundAccessor(RiMethod target, Value[] args, boolean forcedInline) {
+        RiType accessor = target.accessor();
+        if (accessor != null) {
+            assert boundAccessor.get() == null;
+            boundAccessor.set(accessor);
+            try {
+                // What looks like an object receiver in the bytecode may not be a word value
+                compilation.setNotTypesafe();
+                inline(target, args, forcedInline);
+            } finally {
+                boundAccessor.set(null);
+            }
+            return true;
+        }
+        return false;
+    }
+
+    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;
+            }
+            // 2. check if an assumed leaf method can be found
+            RiMethod leaf = getAssumedLeafMethod(target, receiver);
+            if (leaf != null && leaf.isResolved() && !isAbstract(leaf.accessFlags()) && leaf.holder().isResolved()) {
+                if (C1XOptions.PrintAssumptions) {
+                    TTY.println("Optimistic invoke direct because of leaf method to " + leaf);
+                }
+                invokeDirect(leaf, args, null, cpi, constantPool);
+                return;
+            } else if (C1XOptions.PrintAssumptions) {
+                TTY.println("Could not make leaf method assumption for target=" + target + " leaf=" + leaf + " receiver.declaredType=" + receiver.declaredType());
+            }
+            // 3. check if the either of the holder or declared type of receiver can be assumed to be a leaf
+            exact = getAssumedLeafType(klass, receiver);
+            if (exact != null && exact.isResolved()) {
+                RiMethod targetMethod = exact.resolveMethodImpl(target);
+                if (C1XOptions.PrintAssumptions) {
+                    TTY.println("Optimistic invoke direct because of leaf type to " + targetMethod);
+                }
+                // either the holder class is exact, or the receiver object has an exact type
+                invokeDirect(targetMethod, args, exact, cpi, constantPool);
+                return;
+            } else if (C1XOptions.PrintAssumptions) {
+                TTY.println("Could not make leaf type assumption for type " + klass);
+            }
+        }
+        // devirtualization failed, produce an actual invokevirtual
+        appendInvoke(opcode, target, args, false, cpi, constantPool);
+    }
+
+    private CiKind returnKind(RiMethod target) {
+        return target.signature().returnKind();
+    }
+
+    private void invokeDirect(RiMethod target, Value[] args, RiType knownHolder, int cpi, RiConstantPool constantPool) {
+        if (!tryInline(target, args)) {
+            // could not optimize or inline the method call
+            appendInvoke(INVOKESPECIAL, target, args, false, cpi, constantPool);
+        }
+    }
+
+    private void appendInvoke(int opcode, RiMethod target, Value[] args, boolean isStatic, int cpi, RiConstantPool constantPool) {
+        CiKind resultType = returnKind(target);
+        Value result = append(new Invoke(opcode, resultType.stackKind(), args, isStatic, target, target.signature().returnType(compilation.method.holder()), null));
+        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 = compilation.runtime.getTypeOf(receiver.asConstant());
+                }
+                if (exact == null) {
+                    RiType declared = receiver.declaredType();
+                    exact = declared == null || !declared.isResolved() ? null : declared.exactType();
+                }
+            }
+        }
+        return exact;
+    }
+
+    private RiType getAssumedLeafType(RiType type) {
+        if (isFinal(type.accessFlags())) {
+            return type;
+        }
+        RiType assumed = null;
+        if (C1XOptions.UseAssumptions) {
+            assumed = type.uniqueConcreteSubtype();
+            if (assumed != null) {
+                if (C1XOptions.PrintAssumptions) {
+                    TTY.println("Recording concrete subtype assumption in context of " + type.name() + ": " + assumed.name());
+                }
+                compilation.assumptions.recordConcreteSubtype(type, assumed);
+            }
+        }
+        return assumed;
+    }
+
+    private RiType getAssumedLeafType(RiType staticType, Value receiver) {
+        RiType assumed = getAssumedLeafType(staticType);
+        if (assumed != null) {
+            return assumed;
+        }
+        RiType declared = receiver.declaredType();
+        if (declared != null && declared.isResolved()) {
+            assumed = getAssumedLeafType(declared);
+            return assumed;
+        }
+        return null;
+    }
+
+    private RiMethod getAssumedLeafMethod(RiMethod target, Value receiver) {
+        RiMethod assumed = getAssumedLeafMethod(target);
+        if (assumed != null) {
+            return assumed;
+        }
+        RiType declared = receiver.declaredType();
+        if (declared != null && declared.isResolved() && !declared.isInterface()) {
+            RiMethod impl = declared.resolveMethodImpl(target);
+            if (impl != null) {
+                assumed = getAssumedLeafMethod(impl);
+            }
+        }
+        return assumed;
+    }
+
+    void callRegisterFinalizer() {
+        Value receiver = curState.loadLocal(0);
+        RiType declaredType = receiver.declaredType();
+        RiType receiverType = declaredType;
+        RiType exactType = receiver.exactType();
+        if (exactType == null && declaredType != null) {
+            exactType = declaredType.exactType();
+        }
+        if (exactType == null && receiver instanceof Local && ((Local) receiver).javaIndex() == 0) {
+            // the exact type isn't known, but the receiver is parameter 0 => use holder
+            receiverType = compilation.method.holder();
+            exactType = receiverType.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 (compilation.recordNoFinalizableSubclassAssumption(declaredType)) {
+                    needsCheck = false;
+                }
+            }
+
+            if (receiverType != null && !receiverType.hasFinalizableSubclass()) {
+                if (compilation.recordNoFinalizableSubclassAssumption(receiverType)) {
+                    needsCheck = false;
+                }
+            }
+        }
+
+        if (needsCheck) {
+            // append a call to the registration intrinsic
+            loadLocal(0, CiKind.Object);
+            FrameState stateBefore = curState.immutableCopy(bci());
+            append(new Intrinsic(CiKind.Void, C1XIntrinsic.java_lang_Object$init,
+                                 null, curState.popArguments(1), false, stateBefore, true, true));
+            C1XMetrics.InlinedFinalizerChecks++;
+        }
+    }
+
+    void genReturn(Value x) {
+        if (C1XIntrinsic.getIntrinsic(method()) == C1XIntrinsic.java_lang_Object$init) {
+            callRegisterFinalizer();
+        }
+
+        // If inlining, then returns become gotos to the continuation point.
+        if (scopeData.continuation() != null) {
+            if (isSynchronized(method().accessFlags())) {
+                // if the inlined method is synchronized, then the monitor
+                // must be released before jumping to the continuation point
+                assert C1XOptions.OptInlineSynchronized;
+                Value object = curState.lockAt(0);
+                if (object instanceof Instruction) {
+                    Instruction obj = (Instruction) object;
+                    if (!obj.isAppended()) {
+                        appendWithoutOptimization(obj, Instruction.SYNCHRONIZATION_ENTRY_BCI);
+                    }
+                }
+                genMonitorExit(object, Instruction.SYNCHRONIZATION_ENTRY_BCI);
+            }
+
+            // empty stack for return value
+            curState.truncateStack(0);
+            if (x != null) {
+                curState.push(x.kind, x);
+            }
+            Goto gotoCallee = new Goto(scopeData.continuation(), null, false);
+
+            // ATTN: assumption: curState is not used further down, else add .immutableCopy()
+            scopeData.updateSimpleInlineInfo(curBlock, lastInstr, curState);
+
+            // State at end of inlined method is the state of the caller
+            // without the method parameters on stack, including the
+            // return value, if any, of the inlined method on operand stack.
+            curState = scopeData.continuationState().copy();
+            if (x != null) {
+                curState.push(x.kind, x);
+            }
+
+            // The current bci is in the wrong scope, so use the bci of the continuation point.
+            appendWithoutOptimization(gotoCallee, scopeData.continuation().bci());
+            return;
+        }
+
+        curState.truncateStack(0);
+        if (Modifier.isSynchronized(method().accessFlags())) {
+            FrameState stateBefore = curState.immutableCopy(bci());
+            // unlock before exiting the method
+            int lockNumber = curState.totalLocksSize() - 1;
+            MonitorAddress lockAddress = null;
+            if (compilation.runtime.sizeOfBasicObjectLock() != 0) {
+                lockAddress = new MonitorAddress(lockNumber);
+                append(lockAddress);
+            }
+            append(new MonitorExit(rootMethodSynchronizedObject, lockAddress, lockNumber, stateBefore));
+            curState.unlock();
+        }
+        append(new Return(x, !scopeData.noSafepoints()));
+    }
+
+    /**
+     * Gets the number of locks held.
+     */
+    private int locksSize() {
+        return curState.locksSize();
+    }
+
+    void genMonitorEnter(Value x, int bci) {
+        int lockNumber = locksSize();
+        MonitorAddress lockAddress = null;
+        if (compilation.runtime.sizeOfBasicObjectLock() != 0) {
+            lockAddress = new MonitorAddress(lockNumber);
+            append(lockAddress);
+        }
+        MonitorEnter monitorEnter = new MonitorEnter(x, lockAddress, lockNumber, null);
+        appendWithoutOptimization(monitorEnter, bci);
+        curState.lock(scope(), x, lockNumber + 1);
+        monitorEnter.setStateAfter(curState.immutableCopy(bci));
+        killMemoryMap(); // prevent any optimizations across synchronization
+    }
+
+    void genMonitorExit(Value x, int bci) {
+        int lockNumber = curState.totalLocksSize() - 1;
+        if (lockNumber < 0) {
+            throw new CiBailout("monitor stack underflow");
+        }
+        MonitorAddress lockAddress = null;
+        if (compilation.runtime.sizeOfBasicObjectLock() != 0) {
+            lockAddress = new MonitorAddress(lockNumber);
+            append(lockAddress);
+        }
+        appendWithoutOptimization(new MonitorExit(x, lockAddress, lockNumber, null), bci);
+        curState.unlock();
+        killMemoryMap(); // prevent any optimizations across synchronization
+    }
+
+    void genJsr(int dest) {
+        for (ScopeData cur = scopeData; cur != null && cur.parsingJsr() && cur.scope == scope(); cur = cur.parent) {
+            if (cur.jsrEntryBCI() == dest) {
+                // the jsr/ret pattern includes a recursive invocation
+                throw new CiBailout("recursive jsr/ret structure");
+            }
+        }
+        push(CiKind.Jsr, append(Constant.forJsr(nextBCI())));
+        tryInlineJsr(dest);
+    }
+
+    void genRet(int localIndex) {
+        if (!scopeData.parsingJsr()) {
+            throw new CiBailout("ret encountered when not parsing subroutine");
+        }
+
+        if (localIndex != scopeData.jsrEntryReturnAddressLocal()) {
+            throw new CiBailout("jsr/ret structure is too complicated");
+        }
+        // rets become non-safepoint gotos
+        append(new Goto(scopeData.jsrContinuation(), null, false));
+    }
+
+    void genTableswitch() {
+        int bci = bci();
+        BytecodeTableSwitch ts = new BytecodeTableSwitch(stream(), bci);
+        int max = ts.numberOfCases();
+        List<BlockBegin> list = new ArrayList<BlockBegin>(max + 1);
+        boolean isBackwards = false;
+        for (int i = 0; i < max; i++) {
+            // add all successors to the successor list
+            int offset = ts.offsetAt(i);
+            list.add(blockAt(bci + offset));
+            isBackwards |= offset < 0; // track if any of the successors are backwards
+        }
+        int offset = ts.defaultOffset();
+        isBackwards |= offset < 0; // if the default successor is backwards
+        list.add(blockAt(bci + offset));
+        boolean isSafepoint = isBackwards && !scopeData.noSafepoints();
+        FrameState stateBefore = isSafepoint ? curState.immutableCopy(bci()) : null;
+        append(new TableSwitch(ipop(), list, ts.lowKey(), stateBefore, isSafepoint));
+    }
+
+    void genLookupswitch() {
+        int bci = bci();
+        BytecodeLookupSwitch ls = new BytecodeLookupSwitch(stream(), bci);
+        int max = ls.numberOfCases();
+        List<BlockBegin> list = new ArrayList<BlockBegin>(max + 1);
+        int[] keys = new int[max];
+        boolean isBackwards = false;
+        for (int i = 0; i < max; i++) {
+            // add all successors to the successor list
+            int offset = ls.offsetAt(i);
+            list.add(blockAt(bci + offset));
+            keys[i] = ls.keyAt(i);
+            isBackwards |= offset < 0; // track if any of the successors are backwards
+        }
+        int offset = ls.defaultOffset();
+        isBackwards |= offset < 0; // if the default successor is backwards
+        list.add(blockAt(bci + offset));
+        boolean isSafepoint = isBackwards && !scopeData.noSafepoints();
+        FrameState stateBefore = isSafepoint ? curState.immutableCopy(bci()) : null;
+        append(new LookupSwitch(ipop(), list, keys, stateBefore, isSafepoint));
+    }
+
+    /**
+     * Determines whether the length of an array should be extracted out as a separate instruction
+     * before an array indexing instruction. This exposes it to CSE.
+     * @param array
+     * @return
+     */
+    private boolean cseArrayLength(Value array) {
+        // checks whether an array length access should be generated for CSE
+        if (C1XOptions.OptCSEArrayLength) {
+            // always access the length for CSE
+            return true;
+        } else if (array.isConstant()) {
+            // the array itself is a constant
+            return true;
+        } else if (array instanceof LoadField && ((LoadField) array).constantValue() != null) {
+            // the length is derived from a constant array
+            return true;
+        } else if (array instanceof NewArray) {
+            // the array is derived from an allocation
+            final Value length = ((NewArray) array).length();
+            return length != null && length.isConstant();
+        }
+        return false;
+    }
+
+    private Value appendConstant(CiConstant type) {
+        return appendWithBCI(new Constant(type), bci(), false);
+    }
+
+    private Value append(Instruction x) {
+        return appendWithBCI(x, bci(), C1XOptions.OptCanonicalize);
+    }
+
+    private Value appendWithoutOptimization(Instruction x, int bci) {
+        return appendWithBCI(x, bci, false);
+    }
+
+    private Value appendWithBCI(Instruction x, int bci, boolean canonicalize) {
+        if (canonicalize) {
+            // attempt simple constant folding and strength reduction
+            Value r = canonicalizer.canonicalize(x);
+            List<Instruction> extra = canonicalizer.extra();
+            if (extra != null) {
+                // the canonicalization introduced instructions that should be added before this
+                for (Instruction i : extra) {
+                    appendWithBCI(i, bci, false); // don't try to canonicalize the new instructions
+                }
+            }
+            if (r instanceof Instruction) {
+                // the result is an instruction that may need to be appended
+                x = (Instruction) r;
+            } else {
+                // the result is not an instruction (and thus cannot be appended)
+                return r;
+            }
+        }
+        if (x.isAppended()) {
+            // the instruction has already been added
+            return x;
+        }
+        if (localValueMap != null) {
+            // look in the local value map
+            Value r = localValueMap.findInsert(x);
+            if (r != x) {
+                C1XMetrics.LocalValueNumberHits++;
+                if (r instanceof Instruction) {
+                    assert ((Instruction) r).isAppended() : "instruction " + r + "is not appended";
+                }
+                return r;
+            }
+        }
+
+        assert x.next() == null : "instruction should not have been appended yet";
+        assert lastInstr.next() == null : "cannot append instruction to instruction which isn't end (" + lastInstr + "->" + lastInstr.next() + ")";
+        if (lastInstr instanceof Base) {
+            assert x instanceof Intrinsic : "may only happen when inlining intrinsics";
+            Instruction prev = lastInstr.prev(lastInstr.block());
+            prev.setNext(x, bci);
+            x.setNext(lastInstr, bci);
+        } else {
+            lastInstr = lastInstr.setNext(x, bci);
+        }
+        if (++stats.nodeCount >= C1XOptions.MaximumInstructionCount) {
+            // bailout if we've exceeded the maximum inlining size
+            throw new CiBailout("Method and/or inlining is too large");
+        }
+
+        if (memoryMap != null && hasUncontrollableSideEffects(x)) {
+            // conservatively kill all memory if there are unknown side effects
+            memoryMap.kill();
+        }
+
+        if (x instanceof StateSplit) {
+            StateSplit stateSplit = (StateSplit) x;
+            if (!stateSplit.isStateCleared() && stateSplit.stateBefore() == null) {
+                stateSplit.setStateBefore(curState.immutableCopy(bci));
+            }
+        }
+
+        if (x.canTrap()) {
+            // connect the instruction to any exception handlers
+            x.setExceptionHandlers(handleException(x, bci));
+        }
+
+        return x;
+    }
+
+    private boolean hasUncontrollableSideEffects(Value x) {
+        return x instanceof Invoke || x instanceof Intrinsic && !((Intrinsic) x).preservesState() || x instanceof ResolveClass;
+    }
+
+    private BlockBegin blockAtOrNull(int bci) {
+        return scopeData.blockAt(bci);
+    }
+
+    private BlockBegin blockAt(int bci) {
+        BlockBegin result = blockAtOrNull(bci);
+        assert result != null : "Expected a block to begin at " + bci;
+        return result;
+    }
+
+    boolean tryInlineJsr(int jsrStart) {
+        // start a new continuation point.
+        // all ret instructions will be replaced with gotos to this point
+        BlockBegin cont = blockAt(nextBCI());
+
+        // push callee scope
+        pushScopeForJsr(cont, jsrStart);
+
+        BlockBegin jsrStartBlock = blockAt(jsrStart);
+        assert !jsrStartBlock.wasVisited();
+        Goto gotoSub = new Goto(jsrStartBlock, null, false);
+        gotoSub.setStateAfter(curState.immutableCopy(bci()));
+        assert jsrStartBlock.stateBefore() == null;
+        jsrStartBlock.setStateBefore(curState.immutableCopy(bci()));
+        append(gotoSub);
+        curBlock.setEnd(gotoSub);
+        lastInstr = curBlock = jsrStartBlock;
+
+        scopeData.addToWorkList(jsrStartBlock);
+
+        iterateAllBlocks();
+
+        if (cont.stateBefore() != null) {
+            if (!cont.wasVisited()) {
+                scopeData.parent.addToWorkList(cont);
+            }
+        }
+
+        BlockBegin jsrCont = scopeData.jsrContinuation();
+        assert jsrCont == cont && (!jsrCont.wasVisited() || jsrCont.isParserLoopHeader());
+        assert lastInstr != null && lastInstr instanceof BlockEnd;
+
+        // continuation is in work list, so end iteration of current block
+        skipBlock = true;
+        popScopeForJsr();
+        C1XMetrics.InlinedJsrs++;
+        return true;
+    }
+
+    void pushScopeForJsr(BlockBegin jsrCont, int jsrStart) {
+        BytecodeStream stream = new BytecodeStream(scope().method.code());
+        RiConstantPool constantPool = scopeData.constantPool;
+        ScopeData data = new ScopeData(scopeData, scope(), scopeData.blockMap, stream, constantPool, jsrStart);
+        BlockBegin continuation = scopeData.continuation();
+        data.setContinuation(continuation);
+        if (continuation != null) {
+            assert scopeData.continuationState() != null;
+            data.setContinuationState(scopeData.continuationState().copy());
+        }
+        data.setJsrContinuation(jsrCont);
+        scopeData = data;
+    }
+
+    void pushScope(RiMethod target, BlockBegin continuation) {
+        // prepare callee scope
+        IRScope calleeScope = new IRScope(scope(), curState.immutableCopy(bci()), target, -1);
+        BlockMap blockMap = compilation.getBlockMap(calleeScope.method, -1);
+        calleeScope.setStoresInLoops(blockMap.getStoresInLoops());
+        // prepare callee state
+        curState = curState.pushScope(calleeScope);
+        BytecodeStream stream = new BytecodeStream(target.code());
+        RiConstantPool constantPool = compilation.runtime.getConstantPool(target);
+        ScopeData data = new ScopeData(scopeData, calleeScope, blockMap, stream, constantPool);
+        data.setContinuation(continuation);
+        scopeData = data;
+    }
+
+    MutableFrameState stateAtEntry(RiMethod method) {
+        MutableFrameState state = new MutableFrameState(scope(), -1, method.maxLocals(), method.maxStackSize());
+        int index = 0;
+        if (!isStatic(method.accessFlags())) {
+            // add the receiver and assume it is non null
+            Local local = new Local(method.holder().kind(), index);
+            local.setFlag(Value.Flag.NonNull, true);
+            local.setDeclaredType(method.holder());
+            state.storeLocal(index, local);
+            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);
+            if (type.isResolved()) {
+                local.setDeclaredType(type);
+            }
+            state.storeLocal(index, local);
+            index += kind.sizeInSlots();
+        }
+        return state;
+    }
+
+    boolean tryRemoveCall(RiMethod target, Value[] args, boolean isStatic) {
+        if (target.isResolved()) {
+            if (C1XOptions.OptIntrinsify) {
+                // try to create an intrinsic node instead of a call
+                C1XIntrinsic intrinsic = C1XIntrinsic.getIntrinsic(target);
+                if (intrinsic != null && tryInlineIntrinsic(target, args, isStatic, intrinsic)) {
+                    // this method is not an intrinsic
+                    return true;
+                }
+            }
+            if (C1XOptions.CanonicalizeFoldableMethods) {
+                // next try to fold the method call
+                if (tryFoldable(target, args)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private boolean tryInlineIntrinsic(RiMethod target, Value[] args, boolean isStatic, C1XIntrinsic intrinsic) {
+        boolean preservesState = true;
+        boolean canTrap = false;
+
+        Instruction result = null;
+
+        // handle intrinsics differently
+        switch (intrinsic) {
+
+            case java_lang_System$arraycopy:
+                if (compilation.runtime.supportsArrayIntrinsics()) {
+                    break;
+                } else {
+                    return false;
+                }
+            case java_lang_Object$getClass:
+                canTrap = true;
+                break;
+            case java_lang_Thread$currentThread:
+                break;
+            case java_util_Arrays$copyOf:
+                if (args[0].declaredType() != null && args[0].declaredType().isArrayClass() && compilation.runtime.supportsArrayIntrinsics()) {
+                    break;
+                } else {
+                    return false;
+                }
+            case java_lang_Object$init: // fall through
+            case java_lang_String$equals: // fall through
+            case java_lang_String$compareTo: // fall through
+            case java_lang_String$indexOf: // fall through
+            case java_lang_Math$max: // fall through
+            case java_lang_Math$min: // fall through
+            case java_lang_Math$atan2: // fall through
+            case java_lang_Math$pow: // fall through
+            case java_lang_Math$exp: // fall through
+            case java_nio_Buffer$checkIndex: // fall through
+            case java_lang_System$identityHashCode: // fall through
+            case java_lang_System$currentTimeMillis: // fall through
+            case java_lang_System$nanoTime: // fall through
+            case java_lang_Object$hashCode: // fall through
+            case java_lang_Class$isAssignableFrom: // fall through
+            case java_lang_Class$isInstance: // fall through
+            case java_lang_Class$getModifiers: // fall through
+            case java_lang_Class$isInterface: // fall through
+            case java_lang_Class$isArray: // fall through
+            case java_lang_Class$isPrimitive: // fall through
+            case java_lang_Class$getSuperclass: // fall through
+            case java_lang_Class$getComponentType: // fall through
+            case java_lang_reflect_Array$getLength: // fall through
+            case java_lang_reflect_Array$newArray: // fall through
+            case java_lang_Double$doubleToLongBits: // fall through
+            case java_lang_Float$floatToIntBits: // fall through
+            case java_lang_Math$sin: // fall through
+            case java_lang_Math$cos: // fall through
+            case java_lang_Math$tan: // fall through
+            case java_lang_Math$log: // fall through
+            case java_lang_Math$log10: // fall through
+            case java_lang_Integer$bitCount: // fall through
+            case java_lang_Integer$reverseBytes: // fall through
+            case java_lang_Long$bitCount: // fall through
+            case java_lang_Long$reverseBytes: // fall through
+            case java_lang_Object$clone:  return false;
+            // TODO: preservesState and canTrap for complex intrinsics
+        }
+
+
+
+        // get the arguments for the intrinsic
+        CiKind resultType = returnKind(target);
+
+        if (C1XOptions.PrintInlinedIntrinsics) {
+            TTY.println("Inlining intrinsic: " + intrinsic);
+        }
+
+        // Create state before intrinsic.
+        for (int i = 0; i < args.length; ++i) {
+            if (args[i] != null) {
+                curState.push(args[i].kind.stackKind(), args[i]);
+            }
+        }
+
+        // Create the intrinsic node.
+        if (intrinsic == C1XIntrinsic.java_lang_System$arraycopy) {
+            result = genArrayCopy(target, args);
+        } else if (intrinsic == C1XIntrinsic.java_util_Arrays$copyOf) {
+            result = genArrayClone(target, args);
+        } else {
+            result = new Intrinsic(resultType.stackKind(), intrinsic, target, args, isStatic, curState.immutableCopy(bci()), preservesState, canTrap);
+        }
+
+        // Pop arguments.
+        curState.popArguments(args.length);
+
+        pushReturn(resultType, append(result));
+        stats.intrinsicCount++;
+        return true;
+    }
+
+    private Instruction genArrayClone(RiMethod target, Value[] args) {
+        FrameState state = curState.immutableCopy(bci());
+        Value array = args[0];
+        RiType type = array.declaredType();
+        assert type != null && type.isResolved() && type.isArrayClass();
+        Value newLength = args[1];
+
+        Value oldLength = append(new ArrayLength(array, state));
+        Value newArray = append(new NewObjectArrayClone(newLength, array, state));
+        Value copyLength = append(new IfOp(newLength, Condition.LT, oldLength, newLength, oldLength));
+        append(new ArrayCopy(array, Constant.forInt(0), newArray, Constant.forInt(0), copyLength, null, null));
+        return (Instruction) newArray;
+    }
+
+    private Instruction genArrayCopy(RiMethod target, Value[] args) {
+        FrameState state = curState.immutableCopy(bci());
+        Instruction result;
+        Value src = args[0];
+        Value srcPos = args[1];
+        Value dest = args[2];
+        Value destPos = args[3];
+        Value length = args[4];
+
+        // Check src start pos.
+        Value srcLength = append(new ArrayLength(src, state));
+
+        // Check dest start pos.
+        Value destLength = srcLength;
+        if (src != dest) {
+            destLength = append(new ArrayLength(dest, state));
+        }
+
+        // Check src end pos.
+        Value srcEndPos = append(new ArithmeticOp(IADD, CiKind.Int, srcPos, length, false, null));
+        append(new BoundsCheck(srcEndPos, srcLength, state, Condition.LE));
+
+        // Check dest end pos.
+        Value destEndPos = srcEndPos;
+        if (destPos != srcPos) {
+            destEndPos = append(new ArithmeticOp(IADD, CiKind.Int, destPos, length, false, null));
+        }
+        append(new BoundsCheck(destEndPos, destLength, state, Condition.LE));
+
+        Value zero = append(Constant.forInt(0));
+        append(new BoundsCheck(length, zero, state, Condition.GE));
+        append(new BoundsCheck(srcPos, zero, state, Condition.GE));
+        append(new BoundsCheck(destPos, zero, state, Condition.GE));
+
+        result = new ArrayCopy(src, srcPos, dest, destPos, length, target, state);
+        return result;
+    }
+
+    private boolean tryFoldable(RiMethod target, Value[] args) {
+        CiConstant result = Canonicalizer.foldInvocation(compilation.runtime, target, args);
+        if (result != null) {
+            if (C1XOptions.TraceBytecodeParserLevel > 0) {
+                log.println("|");
+                log.println("|   [folded " + target + " --> " + result + "]");
+                log.println("|");
+            }
+
+            pushReturn(returnKind(target), append(new Constant(result)));
+            return true;
+        }
+        return false;
+    }
+
+    private boolean tryInline(RiMethod target, Value[] args) {
+        boolean forcedInline = compilation.runtime.mustInline(target);
+        if (forcedInline) {
+            for (IRScope scope = scope().caller; scope != null; scope = scope.caller) {
+                if (scope.method.equals(target)) {
+                    throw new CiBailout("Cannot recursively inline method that is force-inlined: " + target);
+                }
+            }
+            C1XMetrics.InlineForcedMethods++;
+        }
+        if (forcedInline || checkInliningConditions(target)) {
+            if (C1XOptions.TraceBytecodeParserLevel > 0) {
+                log.adjustIndentation(1);
+                log.println("\\");
+                log.adjustIndentation(1);
+                if (C1XOptions.TraceBytecodeParserLevel < TRACELEVEL_STATE) {
+                    log.println("|   [inlining " + target + "]");
+                    log.println("|");
+                }
+            }
+            if (!inlineWithBoundAccessor(target, args, forcedInline)) {
+                inline(target, args, forcedInline);
+            }
+
+            if (C1XOptions.TraceBytecodeParserLevel > 0) {
+                if (C1XOptions.TraceBytecodeParserLevel < TRACELEVEL_STATE) {
+                    log.println("|");
+                    log.println("|   [return to " + curState.scope().method + "]");
+                }
+                log.adjustIndentation(-1);
+                log.println("/");
+                log.adjustIndentation(-1);
+            }
+            return true;
+        }
+        return false;
+    }
+
+    private boolean checkInliningConditions(RiMethod target) {
+        if (!C1XOptions.OptInline) {
+            return false; // all inlining is turned off
+        }
+        if (!target.isResolved()) {
+            return cannotInline(target, "unresolved method");
+        }
+        if (target.code() == null) {
+            return cannotInline(target, "method has no code");
+        }
+        if (!target.holder().isInitialized()) {
+            return cannotInline(target, "holder is not initialized");
+        }
+        if (recursiveInlineLevel(target) > C1XOptions.MaximumRecursiveInlineLevel) {
+            return cannotInline(target, "recursive inlining too deep");
+        }
+        if (target.code().length > scopeData.maxInlineSize()) {
+            return cannotInline(target, "inlinee too large for this level");
+        }
+        if (scopeData.scope.level + 1 > C1XOptions.MaximumInlineLevel) {
+            return cannotInline(target, "inlining too deep");
+        }
+        if (stats.nodeCount > C1XOptions.MaximumDesiredSize) {
+            return cannotInline(target, "compilation already too big " + "(" + compilation.stats.nodeCount + " nodes)");
+        }
+        if (compilation.runtime.mustNotInline(target)) {
+            C1XMetrics.InlineForbiddenMethods++;
+            return cannotInline(target, "inlining excluded by runtime");
+        }
+        if (compilation.runtime.mustNotCompile(target)) {
+            return cannotInline(target, "compile excluded by runtime");
+        }
+        if (isSynchronized(target.accessFlags()) && !C1XOptions.OptInlineSynchronized) {
+            return cannotInline(target, "is synchronized");
+        }
+        if (target.exceptionHandlers().length != 0 && !C1XOptions.OptInlineExcept) {
+            return cannotInline(target, "has exception handlers");
+        }
+        if (!target.hasBalancedMonitors()) {
+            return cannotInline(target, "has unbalanced monitors");
+        }
+        if (target.isConstructor()) {
+            if (compilation.runtime.isExceptionType(target.holder())) {
+                // don't inline constructors of throwable classes unless the inlining tree is
+                // rooted in a throwable class
+                if (!compilation.runtime.isExceptionType(rootScope().method.holder())) {
+                    return cannotInline(target, "don't inline Throwable constructors");
+                }
+            }
+        }
+        return true;
+    }
+
+    private boolean cannotInline(RiMethod target, String reason) {
+        if (C1XOptions.PrintInliningFailures) {
+            TTY.println("Cannot inline " + target.toString() + " into " + compilation.method.toString() + " because of " + reason);
+        }
+        return false;
+    }
+
+    private void inline(RiMethod target, Value[] args, boolean forcedInline) {
+        BlockBegin orig = curBlock;
+        if (!forcedInline && !isStatic(target.accessFlags())) {
+            // the receiver object must be null-checked for instance methods
+            Value receiver = args[0];
+            if (!receiver.isNonNull() && !receiver.kind.isWord()) {
+                NullCheck check = new NullCheck(receiver, null);
+                args[0] = append(check);
+            }
+        }
+
+        // Introduce a new callee continuation point. All return instructions
+        // in the callee will be transformed to Goto's to the continuation
+        BlockBegin continuationBlock = blockAtOrNull(nextBCI());
+        boolean continuationExisted = true;
+        if (continuationBlock == null) {
+            // there was not already a block starting at the next BCI
+            continuationBlock = new BlockBegin(nextBCI(), ir.nextBlockNumber());
+            continuationBlock.setDepthFirstNumber(0);
+            continuationExisted = false;
+        }
+        // record the number of predecessors before inlining, to determine
+        // whether the inlined method has added edges to the continuation
+        int continuationPredecessors = continuationBlock.predecessors().size();
+
+        // push the target scope
+        pushScope(target, continuationBlock);
+
+        // pass parameters into the callee state
+        FrameState calleeState = curState;
+        for (int i = 0; i < args.length; i++) {
+            Value arg = args[i];
+            if (arg != null) {
+                calleeState.storeLocal(i, arg);
+            }
+        }
+
+        // setup state that is used at returns from the inlined method.
+        // this is essentially the state of the continuation block,
+        // but without the return value on the stack.
+        scopeData.setContinuationState(scope().callerState);
+
+        Value lock = null;
+        BlockBegin syncHandler = null;
+        // inline the locking code if the target method is synchronized
+        if (Modifier.isSynchronized(target.accessFlags())) {
+            // lock the receiver object if it is an instance method, the class object otherwise
+            lock = synchronizedObject(curState, target);
+            syncHandler = new BlockBegin(Instruction.SYNCHRONIZATION_ENTRY_BCI, ir.nextBlockNumber());
+            syncHandler.setNext(null, -1);
+            inlineSyncEntry(lock, syncHandler);
+        }
+
+        BlockBegin calleeStartBlock = blockAt(0);
+        if (calleeStartBlock.isParserLoopHeader()) {
+            // the block is a loop header, so we have to insert a goto
+            Goto gotoCallee = new Goto(calleeStartBlock, null, false);
+            gotoCallee.setStateAfter(curState.immutableCopy(bci()));
+            appendWithoutOptimization(gotoCallee, 0);
+            curBlock.setEnd(gotoCallee);
+            calleeStartBlock.mergeOrClone(calleeState);
+            lastInstr = curBlock = calleeStartBlock;
+            scopeData.addToWorkList(calleeStartBlock);
+            // now iterate over all the blocks
+            iterateAllBlocks();
+        } else {
+            // ready to resume parsing inlined method into this block
+            iterateBytecodesForBlock(0, true);
+            // now iterate over the rest of the blocks
+            iterateAllBlocks();
+        }
+
+        assert continuationExisted || !continuationBlock.wasVisited() : "continuation should not have been parsed if we created it";
+
+        ReturnBlock simpleInlineInfo = scopeData.simpleInlineInfo();
+        if (simpleInlineInfo != null && curBlock == orig) {
+            // Optimization: during parsing of the callee we
+            // generated at least one Goto to the continuation block. If we
+            // generated exactly one, and if the inlined method spanned exactly
+            // one block (and we didn't have to Goto its entry), then we snip
+            // off the Goto to the continuation, allowing control to fall
+            // through back into the caller block and effectively performing
+            // block merging. This allows local load elimination and local value numbering
+            // to take place across multiple callee scopes if they are relatively simple, and
+            // is currently essential to making inlining profitable. It also reduces the
+            // number of blocks in the CFG
+            lastInstr = simpleInlineInfo.returnPredecessor;
+            curState = simpleInlineInfo.returnState.popScope();
+            lastInstr.setNext(null, -1);
+        } else if (continuationPredecessors == continuationBlock.predecessors().size()) {
+            // Inlining caused the instructions after the invoke in the
+            // caller to not reachable any more (i.e. no control flow path
+            // in the callee was terminated by a return instruction).
+            // So skip filling this block with instructions!
+            assert continuationBlock == scopeData.continuation();
+            assert lastInstr instanceof BlockEnd;
+            skipBlock = true;
+        } else {
+            // Resume parsing in continuation block unless it was already parsed.
+            // Note that if we don't change lastInstr here, iteration in
+            // iterateBytecodesForBlock will stop when we return.
+            if (!scopeData.continuation().wasVisited()) {
+                // add continuation to work list instead of parsing it immediately
+                assert lastInstr instanceof BlockEnd;
+                scopeData.parent.addToWorkList(scopeData.continuation());
+                skipBlock = true;
+            }
+        }
+
+        // fill the exception handler for synchronized methods with instructions
+        if (syncHandler != null && syncHandler.stateBefore() != null) {
+            // generate unlocking code if the exception handler is reachable
+            fillSyncHandler(lock, syncHandler, true);
+        } else {
+            popScope();
+        }
+
+        stats.inlineCount++;
+    }
+
+    private Value synchronizedObject(FrameState curState2, RiMethod target) {
+        if (isStatic(target.accessFlags())) {
+            Constant classConstant = new Constant(target.holder().getEncoding(Representation.JavaClass));
+            return appendWithoutOptimization(classConstant, Instruction.SYNCHRONIZATION_ENTRY_BCI);
+        } else {
+            return curState2.localAt(0);
+        }
+    }
+
+    private void inlineSyncEntry(Value lock, BlockBegin syncHandler) {
+        genMonitorEnter(lock, Instruction.SYNCHRONIZATION_ENTRY_BCI);
+        syncHandler.setExceptionEntry();
+        syncHandler.setBlockFlag(BlockBegin.BlockFlag.IsOnWorkList);
+        ExceptionHandler handler = new ExceptionHandler(new CiExceptionHandler(0, method().code().length, -1, 0, null));
+        handler.setEntryBlock(syncHandler);
+        scopeData.addExceptionHandler(handler);
+    }
+
+    private void fillSyncHandler(Value lock, BlockBegin syncHandler, boolean inlinedMethod) {
+        BlockBegin origBlock = curBlock;
+        MutableFrameState origState = curState;
+        Instruction origLast = lastInstr;
+
+        lastInstr = curBlock = syncHandler;
+        while (lastInstr.next() != null) {
+            // go forward to the end of the block
+            lastInstr = lastInstr.next();
+        }
+        curState = syncHandler.stateBefore().copy();
+
+        int bci = Instruction.SYNCHRONIZATION_ENTRY_BCI;
+        Value exception = appendWithoutOptimization(new ExceptionObject(curState.immutableCopy(bci)), bci);
+
+        assert lock != null;
+        assert curState.locksSize() > 0 && curState.lockAt(locksSize() - 1) == lock;
+        if (lock instanceof Instruction) {
+            Instruction l = (Instruction) lock;
+            if (!l.isAppended()) {
+                lock = appendWithoutOptimization(l, Instruction.SYNCHRONIZATION_ENTRY_BCI);
+            }
+        }
+        // exit the monitor
+        genMonitorExit(lock, Instruction.SYNCHRONIZATION_ENTRY_BCI);
+
+        // exit the context of the synchronized method
+        if (inlinedMethod) {
+            popScope();
+            bci = curState.scope().callerBCI();
+            curState = curState.popScope();
+        }
+
+        apush(exception);
+        genThrow(bci);
+        BlockEnd end = (BlockEnd) lastInstr;
+        curBlock.setEnd(end);
+        end.setStateAfter(curState.immutableCopy(bci()));
+
+        curBlock = origBlock;
+        curState = origState;
+        lastInstr = origLast;
+    }
+
+    private void iterateAllBlocks() {
+        BlockBegin b;
+        while ((b = scopeData.removeFromWorkList()) != null) {
+            if (!b.wasVisited()) {
+                if (b.isOsrEntry()) {
+                    // this is the OSR entry block, set up edges accordingly
+                    setupOsrEntryBlock();
+                    // this is no longer the OSR entry block
+                    b.setOsrEntry(false);
+                }
+                b.setWasVisited(true);
+                // now parse the block
+                killMemoryMap();
+                curBlock = b;
+                curState = b.stateBefore().copy();
+                lastInstr = b;
+                b.setNext(null, -1);
+
+                iterateBytecodesForBlock(b.bci(), false);
+            }
+        }
+    }
+
+    private void popScope() {
+        int maxLocks = scope().maxLocks();
+        scopeData = scopeData.parent;
+        scope().updateMaxLocks(maxLocks);
+    }
+
+    private void popScopeForJsr() {
+        scopeData = scopeData.parent;
+    }
+
+    private void setupOsrEntryBlock() {
+        assert compilation.isOsrCompilation();
+
+        int osrBCI = compilation.osrBCI;
+        BytecodeStream s = scopeData.stream;
+        RiOsrFrame frame = compilation.getOsrFrame();
+        s.setBCI(osrBCI);
+        s.next(); // XXX: why go to next bytecode?
+
+        // create a new block to contain the OSR setup code
+        ir.osrEntryBlock = new BlockBegin(osrBCI, ir.nextBlockNumber());
+        ir.osrEntryBlock.setOsrEntry(true);
+        ir.osrEntryBlock.setDepthFirstNumber(0);
+
+        // get the target block of the OSR
+        BlockBegin target = scopeData.blockAt(osrBCI);
+        assert target != null && target.isOsrEntry();
+
+        MutableFrameState state = target.stateBefore().copy();
+        ir.osrEntryBlock.setStateBefore(state);
+
+        killMemoryMap();
+        curBlock = ir.osrEntryBlock;
+        curState = state.copy();
+        lastInstr = ir.osrEntryBlock;
+
+        // create the entry instruction which represents the OSR state buffer
+        // input from interpreter / JIT
+        Instruction e = new OsrEntry();
+        e.setFlag(Value.Flag.NonNull, true);
+
+        for (int i = 0; i < state.localsSize(); i++) {
+            Value local = state.localAt(i);
+            Value get;
+            int offset = frame.getLocalOffset(i);
+            if (local != null) {
+                // this is a live local according to compiler
+                if (local.kind.isObject() && !frame.isLiveObject(i)) {
+                    // the compiler thinks this is live, but not the interpreter
+                    // pretend that it passed null
+                    get = appendConstant(CiConstant.NULL_OBJECT);
+                } else {
+                    Value oc = appendConstant(CiConstant.forInt(offset));
+                    get = append(new UnsafeGetRaw(local.kind, e, oc, 0, true));
+                }
+                state.storeLocal(i, get);
+            }
+        }
+
+        assert state.callerState() == null;
+        state.clearLocals();
+        // ATTN: assumption: state is not used further below, else add .immutableCopy()
+        Goto g = new Goto(target, state, false);
+        append(g);
+        ir.osrEntryBlock.setEnd(g);
+        target.mergeOrClone(ir.osrEntryBlock.end().stateAfter());
+    }
+
+    private BlockEnd iterateBytecodesForBlock(int bci, boolean inliningIntoCurrentBlock) {
+        skipBlock = false;
+        assert curState != null;
+        BytecodeStream s = scopeData.stream;
+        s.setBCI(bci);
+
+        BlockBegin block = curBlock;
+        BlockEnd end = null;
+        boolean pushException = block.isExceptionEntry() && block.next() == null;
+        int prevBCI = bci;
+        int endBCI = s.endBCI();
+        boolean blockStart = true;
+
+        while (bci < endBCI) {
+            BlockBegin nextBlock = blockAtOrNull(bci);
+            if (bci == 0 && inliningIntoCurrentBlock) {
+                if (!nextBlock.isParserLoopHeader()) {
+                    // Ignore the block boundary of the entry block of a method
+                    // being inlined unless the block is a loop header.
+                    nextBlock = null;
+                    blockStart = false;
+                }
+            }
+            if (nextBlock != null && nextBlock != block) {
+                // we fell through to the next block, add a goto and break
+                end = new Goto(nextBlock, null, false);
+                lastInstr = lastInstr.setNext(end, prevBCI);
+                break;
+            }
+            // read the opcode
+            int opcode = s.currentBC();
+
+            // check for active JSR during OSR compilation
+            if (compilation.isOsrCompilation() && scope().isTopScope() && scopeData.parsingJsr() && s.currentBCI() == compilation.osrBCI) {
+                throw new CiBailout("OSR not supported while a JSR is active");
+            }
+
+            // push an exception object onto the stack if we are parsing an exception handler
+            if (pushException) {
+                FrameState stateBefore = curState.immutableCopy(bci());
+                apush(append(new ExceptionObject(stateBefore)));
+                pushException = false;
+            }
+
+            traceState();
+            traceInstruction(bci, s, opcode, blockStart);
+            processBytecode(bci, s, opcode);
+
+            prevBCI = bci;
+
+            if (lastInstr instanceof BlockEnd) {
+                end = (BlockEnd) lastInstr;
+                break;
+            }
+            s.next();
+            bci = s.currentBCI();
+            blockStart = false;
+        }
+
+        // stop processing of this block
+        if (skipBlock) {
+            skipBlock = false;
+            return (BlockEnd) lastInstr;
+        }
+
+        // if the method terminates, we don't need the stack anymore
+        if (end instanceof Return || end instanceof Throw) {
+            curState.clearStack();
+        }
+
+        // connect to begin and set state
+        // NOTE that inlining may have changed the block we are parsing
+        assert end != null : "end should exist after iterating over bytecodes";
+        end.setStateAfter(curState.immutableCopy(bci()));
+        curBlock.setEnd(end);
+        // propagate the state
+        for (BlockBegin succ : end.successors()) {
+            assert succ.predecessors().contains(curBlock);
+            succ.mergeOrClone(end.stateAfter());
+            scopeData.addToWorkList(succ);
+        }
+        return end;
+    }
+
+    private void traceState() {
+        if (C1XOptions.TraceBytecodeParserLevel >= TRACELEVEL_STATE && !TTY.isSuppressed()) {
+            log.println(String.format("|   state [nr locals = %d, stack depth = %d, method = %s]", curState.localsSize(), curState.stackSize(), curState.scope().method));
+            for (int i = 0; i < curState.localsSize(); ++i) {
+                Value value = curState.localAt(i);
+                log.println(String.format("|   local[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind.javaName, value));
+            }
+            for (int i = 0; i < curState.stackSize(); ++i) {
+                Value value = curState.stackAt(i);
+                log.println(String.format("|   stack[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind.javaName, value));
+            }
+            for (int i = 0; i < curState.locksSize(); ++i) {
+                Value value = curState.lockAt(i);
+                log.println(String.format("|   lock[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind.javaName, value));
+            }
+        }
+    }
+
+    private void processBytecode(int bci, BytecodeStream s, int opcode) {
+        int cpi;
+
+        // Checkstyle: stop
+        switch (opcode) {
+            case NOP            : /* nothing to do */ break;
+            case ACONST_NULL    : apush(appendConstant(CiConstant.NULL_OBJECT)); break;
+            case ICONST_M1      : ipush(appendConstant(CiConstant.INT_MINUS_1)); break;
+            case ICONST_0       : ipush(appendConstant(CiConstant.INT_0)); break;
+            case ICONST_1       : ipush(appendConstant(CiConstant.INT_1)); break;
+            case ICONST_2       : ipush(appendConstant(CiConstant.INT_2)); break;
+            case ICONST_3       : ipush(appendConstant(CiConstant.INT_3)); break;
+            case ICONST_4       : ipush(appendConstant(CiConstant.INT_4)); break;
+            case ICONST_5       : ipush(appendConstant(CiConstant.INT_5)); break;
+            case LCONST_0       : lpush(appendConstant(CiConstant.LONG_0)); break;
+            case LCONST_1       : lpush(appendConstant(CiConstant.LONG_1)); break;
+            case FCONST_0       : fpush(appendConstant(CiConstant.FLOAT_0)); break;
+            case FCONST_1       : fpush(appendConstant(CiConstant.FLOAT_1)); break;
+            case FCONST_2       : fpush(appendConstant(CiConstant.FLOAT_2)); break;
+            case DCONST_0       : dpush(appendConstant(CiConstant.DOUBLE_0)); break;
+            case DCONST_1       : dpush(appendConstant(CiConstant.DOUBLE_1)); break;
+            case BIPUSH         : ipush(appendConstant(CiConstant.forInt(s.readByte()))); break;
+            case SIPUSH         : ipush(appendConstant(CiConstant.forInt(s.readShort()))); break;
+            case LDC            : // fall through
+            case LDC_W          : // fall through
+            case LDC2_W         : genLoadConstant(s.readCPI()); break;
+            case ILOAD          : loadLocal(s.readLocalIndex(), CiKind.Int); break;
+            case LLOAD          : loadLocal(s.readLocalIndex(), CiKind.Long); break;
+            case FLOAD          : loadLocal(s.readLocalIndex(), CiKind.Float); break;
+            case DLOAD          : loadLocal(s.readLocalIndex(), CiKind.Double); break;
+            case ALOAD          : loadLocal(s.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, s.readLocalIndex()); break;
+            case LSTORE         : storeLocal(CiKind.Long, s.readLocalIndex()); break;
+            case FSTORE         : storeLocal(CiKind.Float, s.readLocalIndex()); break;
+            case DSTORE         : storeLocal(CiKind.Double, s.readLocalIndex()); break;
+            case ASTORE         : storeLocal(CiKind.Object, s.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, curState.immutableCopy(bci())); 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, curState.immutableCopy(bci())); 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(peekKind(), Condition.EQ); break;
+            case IF_ACMPNE      : genIfSame(peekKind(), Condition.NE); break;
+            case GOTO           : genGoto(s.currentBCI(), s.readBranchDest()); break;
+            case JSR            : genJsr(s.readBranchDest()); break;
+            case RET            : genRet(s.readLocalIndex()); break;
+            case TABLESWITCH    : genTableswitch(); break;
+            case LOOKUPSWITCH   : genLookupswitch(); break;
+            case IRETURN        : genReturn(ipop()); break;
+            case LRETURN        : genReturn(lpop()); break;
+            case FRETURN        : genReturn(fpop()); break;
+            case DRETURN        : genReturn(dpop()); break;
+            case ARETURN        : genReturn(apop()); break;
+            case RETURN         : genReturn(null  ); break;
+            case GETSTATIC      : cpi = s.readCPI(); genGetStatic(cpi, constantPool().lookupField(cpi, opcode)); break;
+            case PUTSTATIC      : cpi = s.readCPI(); genPutStatic(cpi, constantPool().lookupField(cpi, opcode)); break;
+            case GETFIELD       : cpi = s.readCPI(); genGetField(cpi, constantPool().lookupField(cpi, opcode)); break;
+            case PUTFIELD       : cpi = s.readCPI(); genPutField(cpi, constantPool().lookupField(cpi, opcode)); break;
+            case INVOKEVIRTUAL  : cpi = s.readCPI(); genInvokeVirtual(constantPool().lookupMethod(cpi, opcode), cpi, constantPool()); break;
+            case INVOKESPECIAL  : cpi = s.readCPI(); genInvokeSpecial(constantPool().lookupMethod(cpi, opcode), null, cpi, constantPool()); break;
+            case INVOKESTATIC   : cpi = s.readCPI(); genInvokeStatic(constantPool().lookupMethod(cpi, opcode), cpi, constantPool()); break;
+            case INVOKEINTERFACE: cpi = s.readCPI(); genInvokeInterface(constantPool().lookupMethod(cpi, opcode), cpi, constantPool()); break;
+            case NEW            : genNewInstance(s.readCPI()); break;
+            case NEWARRAY       : genNewTypeArray(s.readLocalIndex()); break;
+            case ANEWARRAY      : genNewObjectArray(s.readCPI()); break;
+            case ARRAYLENGTH    : genArrayLength(); break;
+            case ATHROW         : genThrow(s.currentBCI()); break;
+            case CHECKCAST      : genCheckCast(); break;
+            case INSTANCEOF     : genInstanceOf(); break;
+            case MONITORENTER   : genMonitorEnter(apop(), s.currentBCI()); break;
+            case MONITOREXIT    : genMonitorExit(apop(), s.currentBCI()); break;
+            case MULTIANEWARRAY : genNewMultiArray(s.readCPI()); break;
+            case IFNULL         : genIfNull(Condition.EQ); break;
+            case IFNONNULL      : genIfNull(Condition.NE); break;
+            case GOTO_W         : genGoto(s.currentBCI(), s.readFarBranchDest()); break;
+            case JSR_W          : genJsr(s.readFarBranchDest()); break;
+            default:
+                processExtendedBytecode(bci, s, opcode);
+        }
+        // Checkstyle: resume
+    }
+
+    private void processExtendedBytecode(int bci, BytecodeStream s, int opcode) {
+        // Checkstyle: stop
+        switch (opcode) {
+            case UNSAFE_CAST    : genUnsafeCast(constantPool().lookupMethod(s.readCPI(), (byte)Bytecodes.UNSAFE_CAST)); break;
+            case WLOAD          : loadLocal(s.readLocalIndex(), CiKind.Word); break;
+            case WLOAD_0        : loadLocal(0, CiKind.Word); break;
+            case WLOAD_1        : loadLocal(1, CiKind.Word); break;
+            case WLOAD_2        : loadLocal(2, CiKind.Word); break;
+            case WLOAD_3        : loadLocal(3, CiKind.Word); break;
+
+            case WSTORE         : storeLocal(CiKind.Word, s.readLocalIndex()); break;
+            case WSTORE_0       : // fall through
+            case WSTORE_1       : // fall through
+            case WSTORE_2       : // fall through
+            case WSTORE_3       : storeLocal(CiKind.Word, opcode - WSTORE_0); break;
+
+            case WCONST_0       : wpush(appendConstant(CiConstant.ZERO)); break;
+            case WDIV           : // fall through
+            case WREM           : genArithmeticOp(CiKind.Word, opcode, curState.immutableCopy(bci())); break;
+            case WDIVI          : genArithmeticOp(CiKind.Word, opcode, CiKind.Word, CiKind.Int, curState.immutableCopy(bci())); break;
+            case WREMI          : genArithmeticOp(CiKind.Int, opcode, CiKind.Word, CiKind.Int, curState.immutableCopy(bci())); break;
+
+            case READREG        : genLoadRegister(s.readCPI()); break;
+            case WRITEREG       : genStoreRegister(s.readCPI()); break;
+            case INCREG         : genIncRegister(s.readCPI()); break;
+
+            case PREAD          : genLoadPointer(PREAD      | (s.readCPI() << 8)); break;
+            case PGET           : genLoadPointer(PGET       | (s.readCPI() << 8)); break;
+            case PWRITE         : genStorePointer(PWRITE    | (s.readCPI() << 8)); break;
+            case PSET           : genStorePointer(PSET      | (s.readCPI() << 8)); break;
+            case PCMPSWP        : genCompareAndSwap(PCMPSWP | (s.readCPI() << 8)); break;
+            case MEMBAR         : genMemoryBarrier(s.readCPI()); break;
+
+            case WRETURN        : genReturn(wpop()); break;
+            case INFOPOINT      : genInfopoint(INFOPOINT | (s.readUByte(bci() + 1) << 16), s.readUByte(bci() + 2) != 0); break;
+            case JNICALL        : genNativeCall(s.readCPI()); break;
+            case JNIOP          : genJniOp(s.readCPI()); break;
+            case ALLOCA         : genStackAllocate(); break;
+
+            case MOV_I2F        : genConvert(opcode, CiKind.Int, CiKind.Float ); break;
+            case MOV_F2I        : genConvert(opcode, CiKind.Float, CiKind.Int ); break;
+            case MOV_L2D        : genConvert(opcode, CiKind.Long, CiKind.Double ); break;
+            case MOV_D2L        : genConvert(opcode, CiKind.Double, CiKind.Long ); break;
+
+            case UCMP           : genUnsignedCompareOp(CiKind.Int, opcode, s.readCPI()); break;
+            case UWCMP          : genUnsignedCompareOp(CiKind.Word, opcode, s.readCPI()); break;
+
+            case STACKHANDLE    : genStackHandle(s.readCPI() == 0); break;
+            case BREAKPOINT_TRAP: genBreakpointTrap(); break;
+            case PAUSE          : genPause(); break;
+            case LSB            : // fall through
+            case MSB            : genSignificantBit(opcode);break;
+
+            case TEMPLATE_CALL  : genTemplateCall(constantPool().lookupMethod(s.readCPI(), (byte)Bytecodes.TEMPLATE_CALL)); break;
+            case ICMP           : genCompareOp(CiKind.Int, opcode, CiKind.Void); break;
+            case WCMP           : genCompareOp(CiKind.Word, opcode, CiKind.Void); 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, BytecodeStream s, int opcode, boolean blockStart) {
+        if (C1XOptions.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 < s.nextBCI(); ++i) {
+                sb.append(' ').append(s.readUByte(i));
+            }
+            log.println(sb.toString());
+        }
+    }
+
+    private void genPause() {
+        append(new Pause());
+    }
+
+    private void genBreakpointTrap() {
+        append(new BreakpointTrap());
+    }
+
+    private void genStackHandle(boolean isCategory1) {
+        Value value = curState.xpop();
+        wpush(append(new StackHandle(value)));
+    }
+
+    private void genStackAllocate() {
+        Value size = pop(CiKind.Int);
+        wpush(append(new StackAllocate(size)));
+    }
+
+    private void genSignificantBit(int opcode) {
+        Value value = pop(CiKind.Word);
+        push(CiKind.Int, append(new SignificantBitOp(value, opcode)));
+    }
+
+    private void appendSnippetCall(RiSnippetCall snippetCall) {
+        Value[] args = new Value[snippetCall.arguments.length];
+        RiMethod snippet = snippetCall.snippet;
+        RiSignature signature = snippet.signature();
+        assert signature.argumentCount(!isStatic(snippet.accessFlags())) == args.length;
+        for (int i = args.length - 1; i >= 0; --i) {
+            CiKind argKind = signature.argumentKindAt(i);
+            if (snippetCall.arguments[i] == null) {
+                args[i] = pop(argKind);
+            } else {
+                args[i] = append(new Constant(snippetCall.arguments[i]));
+            }
+        }
+
+        if (!tryRemoveCall(snippet, args, true)) {
+            if (!tryInline(snippet, args)) {
+                appendInvoke(snippetCall.opcode, snippet, args, true, (char) 0, constantPool());
+            }
+        }
+    }
+
+    private void genJniOp(int operand) {
+        RiSnippets snippets = compilation.runtime.getSnippets();
+        switch (operand) {
+            case JniOp.LINK: {
+                RiMethod nativeMethod = scope().method;
+                RiSnippetCall linkSnippet = snippets.link(nativeMethod);
+                if (linkSnippet.result != null) {
+                    wpush(appendConstant(linkSnippet.result));
+                } else {
+                    appendSnippetCall(linkSnippet);
+                }
+                break;
+            }
+            case JniOp.J2N: {
+                RiMethod nativeMethod = scope().method;
+                appendSnippetCall(snippets.enterNative(nativeMethod));
+                break;
+            }
+            case JniOp.N2J: {
+                RiMethod nativeMethod = scope().method;
+                appendSnippetCall(snippets.enterVM(nativeMethod));
+                break;
+            }
+        }
+    }
+
+    private void genNativeCall(int cpi) {
+        Value nativeFunctionAddress = wpop();
+        RiSignature sig = constantPool().lookupSignature(cpi);
+        Value[] args = curState.popArguments(sig.argumentSlots(false));
+
+        RiMethod nativeMethod = scope().method;
+        CiKind returnKind = sig.returnKind();
+        pushReturn(returnKind, append(new NativeCall(nativeMethod, sig, nativeFunctionAddress, args, null)));
+
+        // Sign extend or zero the upper bits of a return value smaller than an int to
+        // preserve the invariant that all such values are represented by an int
+        // in the VM. We cannot rely on the native C compiler doing this for us.
+        switch (sig.returnKind()) {
+            case Boolean:
+            case Byte: {
+                genConvert(I2B, CiKind.Int, CiKind.Byte);
+                break;
+            }
+            case Short: {
+                genConvert(I2S, CiKind.Int, CiKind.Short);
+                break;
+            }
+            case Char: {
+                genConvert(I2C, CiKind.Int, CiKind.Char);
+                break;
+            }
+        }
+    }
+
+    void genTemplateCall(RiMethod method) {
+        RiSignature sig = method.signature();
+        Value[] args = curState.popArguments(sig.argumentSlots(false));
+        assert args.length <= 2;
+        CiKind returnKind = sig.returnKind();
+        Value address = null;
+        Value receiver = null;
+        if (args.length == 1) {
+            address = args[0];
+            assert address.kind.isWord();
+        } else if (args.length == 2) {
+            address = args[0];
+            assert address.kind.isWord();
+            receiver = args[1];
+            assert receiver.kind.isObject();
+        }
+        pushReturn(returnKind, append(new TemplateCall(returnKind, address, receiver)));
+    }
+
+    private void genInfopoint(int opcode, boolean inclFrame) {
+        // TODO: create slimmer frame state if inclFrame is false
+        FrameState state = curState.immutableCopy(bci());
+        assert opcode != SAFEPOINT || !scopeData.noSafepoints() : "cannot place explicit safepoint in uninterruptible code scope";
+        Value result = append(new Infopoint(opcode, state));
+        if (!result.kind.isVoid()) {
+            push(result.kind, result);
+        }
+    }
+
+    private void genLoadRegister(int registerId) {
+        CiRegister register = compilation.registerConfig.getRegisterForRole(registerId);
+        if (register == null) {
+            throw new CiBailout("Unsupported READREG operand " + registerId);
+        }
+        LoadRegister load = new LoadRegister(CiKind.Word, register);
+        RiRegisterAttributes regAttr = compilation.registerConfig.getAttributesMap()[register.number];
+        if (regAttr.isNonZero) {
+            load.setFlag(Flag.NonNull);
+        }
+        wpush(append(load));
+    }
+
+    private void genStoreRegister(int registerId) {
+        CiRegister register = compilation.registerConfig.getRegisterForRole(registerId);
+        if (register == null) {
+            throw new CiBailout("Unsupported WRITEREG operand " + registerId);
+        }
+        Value value = pop(CiKind.Word);
+        append(new StoreRegister(CiKind.Word, register, value));
+    }
+
+    private void genIncRegister(int registerId) {
+        CiRegister register = compilation.registerConfig.getRegisterForRole(registerId);
+        if (register == null) {
+            throw new CiBailout("Unsupported INCREG operand " + registerId);
+        }
+        Value value = pop(CiKind.Int);
+        append(new IncrementRegister(register, value));
+    }
+
+    /**
+     * Gets the data kind corresponding to a given pointer operation opcode.
+     * The data kind may be more specific than a {@linkplain CiKind#stackKind()}.
+     *
+     * @return the kind of value at the address accessed by the pointer operation denoted by {@code opcode}
+     */
+    private static CiKind dataKindForPointerOp(int opcode) {
+        switch (opcode) {
+            case PGET_BYTE          :
+            case PSET_BYTE          :
+            case PREAD_BYTE         :
+            case PREAD_BYTE_I       :
+            case PWRITE_BYTE        :
+            case PWRITE_BYTE_I      : return CiKind.Byte;
+            case PGET_CHAR          :
+            case PREAD_CHAR         :
+            case PREAD_CHAR_I       : return CiKind.Char;
+            case PGET_SHORT         :
+            case PSET_SHORT         :
+            case PREAD_SHORT        :
+            case PREAD_SHORT_I      :
+            case PWRITE_SHORT       :
+            case PWRITE_SHORT_I     : return CiKind.Short;
+            case PGET_INT           :
+            case PSET_INT           :
+            case PREAD_INT          :
+            case PREAD_INT_I        :
+            case PWRITE_INT         :
+            case PWRITE_INT_I       : return CiKind.Int;
+            case PGET_FLOAT         :
+            case PSET_FLOAT         :
+            case PREAD_FLOAT        :
+            case PREAD_FLOAT_I      :
+            case PWRITE_FLOAT       :
+            case PWRITE_FLOAT_I     : return CiKind.Float;
+            case PGET_LONG          :
+            case PSET_LONG          :
+            case PREAD_LONG         :
+            case PREAD_LONG_I       :
+            case PWRITE_LONG        :
+            case PWRITE_LONG_I      : return CiKind.Long;
+            case PGET_DOUBLE        :
+            case PSET_DOUBLE        :
+            case PREAD_DOUBLE       :
+            case PREAD_DOUBLE_I     :
+            case PWRITE_DOUBLE      :
+            case PWRITE_DOUBLE_I    : return CiKind.Double;
+            case PGET_WORD          :
+            case PSET_WORD          :
+            case PREAD_WORD         :
+            case PREAD_WORD_I       :
+            case PWRITE_WORD        :
+            case PWRITE_WORD_I      : return CiKind.Word;
+            case PGET_REFERENCE     :
+            case PSET_REFERENCE     :
+            case PREAD_REFERENCE    :
+            case PREAD_REFERENCE_I  :
+            case PWRITE_REFERENCE   :
+            case PWRITE_REFERENCE_I : return CiKind.Object;
+            default:
+                throw new CiBailout("Unsupported pointer operation opcode " + opcode + "(" + nameOf(opcode) + ")");
+        }
+    }
+
+    /**
+     * Pops the value producing the scaled-index or the byte offset for a pointer operation.
+     * If compiling for a 64-bit platform and the value is an {@link CiKind#Int} parameter,
+     * then a conversion is inserted to sign extend the int to a word.
+     *
+     * This is required as the value is used as a 64-bit value and so the high 32 bits
+     * need to be correct.
+     *
+     * @param isInt specifies if the value is an {@code int}
+     */
+    private Value popOffsetOrIndexForPointerOp(boolean isInt) {
+        if (isInt) {
+            Value offsetOrIndex = ipop();
+            if (compilation.target.arch.is64bit() && offsetOrIndex instanceof Local) {
+                return append(new Convert(I2L, offsetOrIndex, CiKind.Word));
+            }
+            return offsetOrIndex;
+        }
+        return wpop();
+    }
+
+    private void genLoadPointer(int opcode) {
+        FrameState stateBefore = curState.immutableCopy(bci());
+        CiKind dataKind = dataKindForPointerOp(opcode);
+        Value offsetOrIndex;
+        Value displacement;
+        if ((opcode & 0xff) == PREAD) {
+            offsetOrIndex = popOffsetOrIndexForPointerOp(opcode >= PREAD_BYTE_I && opcode <= PREAD_REFERENCE_I);
+            displacement = null;
+        } else {
+            offsetOrIndex = popOffsetOrIndexForPointerOp(true);
+            displacement = ipop();
+        }
+        Value pointer = wpop();
+        push(dataKind.stackKind(), append(new LoadPointer(dataKind, opcode, pointer, displacement, offsetOrIndex, stateBefore, false)));
+    }
+
+    private void genStorePointer(int opcode) {
+        FrameState stateBefore = curState.immutableCopy(bci());
+        CiKind dataKind = dataKindForPointerOp(opcode);
+        Value value = pop(dataKind.stackKind());
+        Value offsetOrIndex;
+        Value displacement;
+        if ((opcode & 0xff) == PWRITE) {
+            offsetOrIndex = popOffsetOrIndexForPointerOp(opcode >= PWRITE_BYTE_I && opcode <= PWRITE_REFERENCE_I);
+            displacement = null;
+        } else {
+            offsetOrIndex = popOffsetOrIndexForPointerOp(true);
+            displacement = ipop();
+        }
+        Value pointer = wpop();
+        append(new StorePointer(opcode, dataKind, pointer, displacement, offsetOrIndex, value, stateBefore, false));
+    }
+
+    private static CiKind kindForCompareAndSwap(int opcode) {
+        switch (opcode) {
+            case PCMPSWP_INT        :
+            case PCMPSWP_INT_I      : return CiKind.Int;
+            case PCMPSWP_WORD       :
+            case PCMPSWP_WORD_I     : return CiKind.Word;
+            case PCMPSWP_REFERENCE  :
+            case PCMPSWP_REFERENCE_I: return CiKind.Object;
+            default:
+                throw new CiBailout("Unsupported compare-and-swap opcode " + opcode + "(" + nameOf(opcode) + ")");
+        }
+    }
+
+    private void genCompareAndSwap(int opcode) {
+        FrameState stateBefore = curState.immutableCopy(bci());
+        CiKind kind = kindForCompareAndSwap(opcode);
+        Value newValue = pop(kind);
+        Value expectedValue = pop(kind);
+        Value offset;
+        offset = popOffsetOrIndexForPointerOp(opcode >= PCMPSWP_INT_I && opcode <= PCMPSWP_REFERENCE_I);
+        Value pointer = wpop();
+        push(kind, append(new CompareAndSwap(opcode, pointer, offset, expectedValue, newValue, stateBefore, false)));
+    }
+
+
+    private void genMemoryBarrier(int barriers) {
+        int explicitMemoryBarriers = barriers & ~compilation.target.arch.implicitMemoryBarriers;
+        if (explicitMemoryBarriers != 0) {
+            append(new MemoryBarrier(explicitMemoryBarriers));
+        }
+    }
+
+    private void genArrayLength() {
+        FrameState stateBefore = curState.immutableCopy(bci());
+        ipush(append(new ArrayLength(apop(), stateBefore)));
+    }
+
+    void killMemoryMap() {
+        if (localValueMap != null) {
+            localValueMap.killAll();
+        }
+        if (memoryMap != null) {
+            memoryMap.kill();
+        }
+    }
+
+    boolean assumeLeafClass(RiType type) {
+        if (type.isResolved()) {
+            if (isFinal(type.accessFlags())) {
+                return true;
+            }
+
+            if (C1XOptions.UseAssumptions) {
+                RiType assumed = type.uniqueConcreteSubtype();
+                if (assumed != null && assumed == type) {
+                    if (C1XOptions.PrintAssumptions) {
+                        TTY.println("Recording leaf class assumption for " + type.name());
+                    }
+                    compilation.assumptions.recordConcreteSubtype(type, assumed);
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    RiMethod getAssumedLeafMethod(RiMethod method) {
+        if (method.isResolved()) {
+            if (method.isLeafMethod()) {
+                return method;
+            }
+
+            if (C1XOptions.UseAssumptions) {
+                RiMethod assumed = method.uniqueConcreteMethod();
+                if (assumed != null) {
+                    if (C1XOptions.PrintAssumptions) {
+                        TTY.println("Recording concrete method assumption in context of " + method.holder().name() + ": " + assumed.name());
+                    }
+                    compilation.assumptions.recordConcreteMethod(method, assumed);
+                    return assumed;
+                } else {
+                    if (C1XOptions.PrintAssumptions) {
+                        TTY.println("Did not find unique concrete method for " + method);
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    private int recursiveInlineLevel(RiMethod target) {
+        int rec = 0;
+        IRScope scope = scope();
+        while (scope != null) {
+            if (scope.method != target) {
+                break;
+            }
+            scope = scope.caller;
+            rec++;
+        }
+        return rec;
+    }
+
+    private RiConstantPool constantPool() {
+        return scopeData.constantPool;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/graph/IR.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,314 @@
+/*
+ * 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.sun.c1x.graph;
+
+import java.util.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.debug.*;
+import com.sun.c1x.ir.*;
+import com.sun.c1x.observer.*;
+import com.sun.c1x.opt.*;
+import com.sun.c1x.value.*;
+
+/**
+ * This class implements the overall container for the HIR (high-level IR) graph
+ * and directs its construction, optimization, and finalization.
+ *
+ * @author Thomas Wuerthinger
+ * @author Ben L. Titzer
+ */
+public class IR {
+
+    /**
+     * The compilation associated with this IR.
+     */
+    public final C1XCompilation compilation;
+
+    /**
+     * The start block of this IR.
+     */
+    public BlockBegin startBlock;
+
+    /**
+     * The entry block for an OSR compile.
+     */
+    public BlockBegin osrEntryBlock;
+
+    /**
+     * The top IRScope.
+     */
+    public IRScope topScope;
+
+    /**
+     * The linear-scan ordered list of blocks.
+     */
+    private List<BlockBegin> orderedBlocks;
+
+    /**
+     * Creates a new IR instance for the specified compilation.
+     * @param compilation the compilation
+     */
+    public IR(C1XCompilation compilation) {
+        this.compilation = compilation;
+    }
+
+    /**
+     * Builds the graph, optimizes it, and computes the linear scan block order.
+     */
+    public void build() {
+        if (C1XOptions.PrintTimers) {
+            C1XTimers.HIR_CREATE.start();
+        }
+
+        buildGraph();
+
+        if (C1XOptions.PrintTimers) {
+            C1XTimers.HIR_CREATE.stop();
+            C1XTimers.HIR_OPTIMIZE.start();
+        }
+
+        optimize1();
+        computeLinearScanOrder();
+        optimize2();
+
+        if (C1XOptions.PrintTimers) {
+            C1XTimers.HIR_OPTIMIZE.stop();
+        }
+    }
+
+    private void buildGraph() {
+        topScope = new IRScope(null, null, compilation.method, compilation.osrBCI);
+
+        // Graph builder must set the startBlock and the osrEntryBlock
+        new GraphBuilder(compilation, this).build(topScope);
+        assert startBlock != null;
+        verifyAndPrint("After graph building");
+
+        if (C1XOptions.PrintCompilation) {
+            TTY.print(String.format("%3d blocks | ", this.numberOfBlocks()));
+        }
+    }
+
+    private void optimize1() {
+        if (!compilation.isTypesafe()) {
+            new UnsafeCastEliminator(this);
+            verifyAndPrint("After unsafe cast elimination");
+        }
+
+        // do basic optimizations
+        if (C1XOptions.PhiSimplify) {
+            new PhiSimplifier(this);
+            verifyAndPrint("After phi simplification");
+        }
+        if (C1XOptions.OptNullCheckElimination) {
+            new NullCheckEliminator(this);
+            verifyAndPrint("After null check elimination");
+        }
+        if (C1XOptions.OptDeadCodeElimination1) {
+            new LivenessMarker(this).removeDeadCode();
+            verifyAndPrint("After dead code elimination 1");
+        }
+        if (C1XOptions.OptCEElimination) {
+            new CEEliminator(this);
+            verifyAndPrint("After CEE elimination");
+        }
+        if (C1XOptions.OptBlockMerging) {
+            new BlockMerger(this);
+            verifyAndPrint("After block merging");
+        }
+
+        if (compilation.compiler.extensions != null) {
+            for (C1XCompilerExtension ext : compilation.compiler.extensions) {
+                ext.run(this);
+            }
+        }
+    }
+
+    private void computeLinearScanOrder() {
+        if (C1XOptions.GenLIR) {
+            makeLinearScanOrder();
+            verifyAndPrint("After linear scan order");
+        }
+    }
+
+    private void makeLinearScanOrder() {
+        if (orderedBlocks == null) {
+            CriticalEdgeFinder finder = new CriticalEdgeFinder(this);
+            startBlock.iteratePreOrder(finder);
+            finder.splitCriticalEdges();
+            ComputeLinearScanOrder computeLinearScanOrder = new ComputeLinearScanOrder(compilation.stats.blockCount, startBlock);
+            orderedBlocks = computeLinearScanOrder.linearScanOrder();
+            compilation.stats.loopCount = computeLinearScanOrder.numLoops();
+            computeLinearScanOrder.printBlocks();
+        }
+    }
+
+    private void optimize2() {
+        // do more advanced, dominator-based optimizations
+        if (C1XOptions.OptGlobalValueNumbering) {
+            makeLinearScanOrder();
+            new GlobalValueNumberer(this);
+            verifyAndPrint("After global value numbering");
+        }
+        if (C1XOptions.OptDeadCodeElimination2) {
+            new LivenessMarker(this).removeDeadCode();
+            verifyAndPrint("After dead code elimination 2");
+        }
+
+    }
+
+    /**
+     * Gets the linear scan ordering of blocks as a list.
+     * @return the blocks in linear scan order
+     */
+    public List<BlockBegin> linearScanOrder() {
+        return orderedBlocks;
+    }
+
+    private void print(boolean cfgOnly) {
+        if (!TTY.isSuppressed()) {
+            TTY.println("IR for " + compilation.method);
+            final InstructionPrinter ip = new InstructionPrinter(TTY.out());
+            final BlockPrinter bp = new BlockPrinter(this, ip, cfgOnly, false);
+            startBlock.iteratePreOrder(bp);
+        }
+    }
+
+    /**
+     * Verifies the IR and prints it out if the relevant options are set.
+     * @param phase the name of the phase for printing
+     */
+    public void verifyAndPrint(String phase) {
+        printToTTY(phase);
+
+        if (compilation.compiler.isObserved()) {
+            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, phase, startBlock, true, false));
+        }
+    }
+
+    private void printToTTY(String phase) {
+        if (C1XOptions.PrintHIR && !TTY.isSuppressed()) {
+            TTY.println(phase);
+            print(false);
+        }
+    }
+
+    /**
+     * Creates and inserts a new block between this block and the specified successor,
+     * altering the successor and predecessor lists of involved blocks appropriately.
+     * @param source the source of the edge
+     * @param target the successor before which to insert a block
+     * @return the new block inserted
+     */
+    public BlockBegin splitEdge(BlockBegin source, BlockBegin target) {
+        int bci;
+        if (target.predecessors().size() == 1) {
+            bci = target.bci();
+        } else {
+            bci = source.end().bci();
+        }
+
+        // create new successor and mark it for special block order treatment
+        BlockBegin newSucc = new BlockBegin(bci, nextBlockNumber());
+
+        newSucc.setCriticalEdgeSplit(true);
+
+        // This goto is not a safepoint.
+        Goto e = new Goto(target, null, false);
+        newSucc.setNext(e, bci);
+        newSucc.setEnd(e);
+        // setup states
+        FrameState s = source.end().stateAfter();
+        newSucc.setStateBefore(s);
+        e.setStateAfter(s);
+        assert newSucc.stateBefore().localsSize() == s.localsSize();
+        assert newSucc.stateBefore().stackSize() == s.stackSize();
+        assert newSucc.stateBefore().locksSize() == s.locksSize();
+        // link predecessor to new block
+        source.end().substituteSuccessor(target, newSucc);
+
+        // The ordering needs to be the same, so remove the link that the
+        // set_end call above added and substitute the new_sux for this
+        // block.
+        target.removePredecessor(newSucc);
+
+        // the successor could be the target of a switch so it might have
+        // multiple copies of this predecessor, so substitute the new_sux
+        // for the first and delete the rest.
+        List<BlockBegin> list = target.predecessors();
+        int x = list.indexOf(source);
+        assert x >= 0;
+        list.set(x, newSucc);
+        newSucc.addPredecessor(source);
+        Iterator<BlockBegin> iterator = list.iterator();
+        while (iterator.hasNext()) {
+            if (iterator.next() == source) {
+                iterator.remove();
+                newSucc.addPredecessor(source);
+            }
+        }
+        return newSucc;
+    }
+
+    public void replaceBlock(BlockBegin oldBlock, BlockBegin newBlock) {
+        assert !oldBlock.isExceptionEntry() : "cannot replace exception handler blocks (yet)";
+        for (BlockBegin succ : oldBlock.end().successors()) {
+            succ.removePredecessor(oldBlock);
+        }
+        for (BlockBegin pred : oldBlock.predecessors()) {
+            // substitute the new successor for this block in each predecessor
+            pred.end().substituteSuccessor(oldBlock, newBlock);
+            // and add each predecessor to the successor
+            newBlock.addPredecessor(pred);
+        }
+        // this block is now disconnected; remove all its incoming and outgoing edges
+        oldBlock.predecessors().clear();
+        oldBlock.end().successors().clear();
+    }
+
+    /**
+     * Disconnects the specified block from all other blocks.
+     * @param block the block to remove from the graph
+     */
+    public void disconnectFromGraph(BlockBegin block) {
+        for (BlockBegin p : block.predecessors()) {
+            p.end().successors().remove(block);
+        }
+        for (BlockBegin s : block.end().successors()) {
+            s.predecessors().remove(block);
+        }
+    }
+
+    public int nextBlockNumber() {
+        return compilation.stats.blockCount++;
+    }
+
+    public int numberOfBlocks() {
+        return compilation.stats.blockCount;
+    }
+
+    public int numLoops() {
+        return compilation.stats.loopCount;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/graph/MemoryMap.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,167 @@
+/*
+ * 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.sun.c1x.graph;
+
+import static java.lang.reflect.Modifier.*;
+
+import java.util.*;
+
+import com.sun.c1x.ir.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code MemoryMap} class is an approximation of memory that is used redundant load and
+ * store elimination. In C1, tracking of fields of new objects' fields was precise,
+ * while tracking of other fields is managed at the offset granularity (i.e. a write of a field with offset
+ * {@code off} will "overwrite" all fields with the offset {@code off}. However, C1X distinguishes all
+ * loaded fields as separate locations. Static fields have just one location, while instance fields are
+ * tracked for at most one instance object. Loads or stores of unloaded fields kill all memory locations.
+ * An object is no longer "new" if it is stored into a field or array.
+ *
+ * @author Ben L. Titzer
+ */
+public class MemoryMap {
+
+    private final HashMap<RiField, Value> objectMap = new HashMap<RiField, Value>();
+    private final HashMap<RiField, Value> valueMap = new HashMap<RiField, Value>();
+    private final IdentityHashMap<Value, Value> newObjects = new IdentityHashMap<Value, Value>();
+
+    /**
+     * Kills all memory locations.
+     */
+    public void kill() {
+        objectMap.clear();
+        valueMap.clear();
+        newObjects.clear();
+    }
+
+    /**
+     * The specified instruction has just escaped, it can no longer be considered a "new object".
+     * @param x the instruction that just escaped
+     */
+    public void storeValue(Value x) {
+        newObjects.remove(x);
+    }
+
+    /**
+     * Record a newly allocated object.
+     * @param n the instruction generating the new object
+     */
+    public void newInstance(NewInstance n) {
+        newObjects.put(n, n);
+    }
+
+    /**
+     * Look up a load for load elimination, and put this load into the load elimination map.
+     * @param load the instruction representing the load
+     * @return a reference to the previous instruction that already loaded the value, if it is available; the
+     * {@code load} parameter otherwise
+     */
+    public Value load(LoadField load) {
+        if (!load.isLoaded()) {
+            // the field is not loaded, kill everything, because it will need to be resolved
+            kill();
+            return load;
+        }
+        RiField field = load.field();
+        if (load.isStatic()) {
+            // the field is static, look in the static map
+            Value r = valueMap.get(field);
+            if (r != null) {
+                return r;
+            }
+            valueMap.put(field, load);
+        } else {
+            // see if the value for this object for this field is in the map
+            if (objectMap.get(field) == load.object()) {
+                return valueMap.get(field);
+            }
+            objectMap.put(field, load.object());
+            valueMap.put(field, load);
+        }
+
+        return load; // load cannot be eliminated
+    }
+
+    /**
+     * Insert a new result for a load into the memory map.
+     * @param load the load instruction
+     * @param result the result that the load instruction should produce
+     */
+    public void setResult(LoadField load, Value result) {
+        if (load.isLoaded()) {
+            RiField field = load.field();
+            if (load.isStatic()) {
+                // the field is static, put it in the static map
+                valueMap.put(field, result);
+            } else {
+                // put the result for the loaded object into the map
+                objectMap.put(field, load.object());
+                valueMap.put(field, result);
+            }
+        }
+    }
+
+    /**
+     * Look up a store for store elimination, and put this store into the load elimination map.
+     * @param store the store instruction to put into the map
+     * @return {@code null} if the store operation is redundant; the {@code store} parameter
+     * otherwise
+     */
+    public StoreField store(StoreField store) {
+        if (!store.isLoaded()) {
+            // the field is not loaded, kill everything, because it will need to be resolved
+            kill();
+            return store;
+        }
+        RiField field = store.field();
+        Value value = store.value();
+        if (store.isStatic()) {
+            // the field is static, overwrite it into the static map
+            valueMap.put(field, value);
+        } else {
+            if (newObjects.containsKey(store.object())) {
+                // this is a store to a new object's field
+                if (fieldHasNoStores(field) && value.isConstant() && value.asConstant().isDefaultValue()) {
+                    // this is a redundant initialization of a new object's field that has not been assigned to
+                    return null;
+                }
+            }
+            Value obj = objectMap.get(field);
+            if (obj == store.object()) {
+                // is this a redundant store?
+                if (value == valueMap.get(field) && !isVolatile(field.accessFlags())) {
+                    return null;
+                }
+            }
+            objectMap.put(field, store.object());
+            valueMap.put(field, value);
+        }
+        storeValue(value); // the value stored just escaped
+        return store; // the store cannot be eliminated
+    }
+
+    private boolean fieldHasNoStores(RiField field) {
+        return objectMap.get(field) == null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/graph/ScopeData.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,511 @@
+/*
+ * 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.sun.c1x.graph;
+
+import static com.sun.c1x.graph.ScopeData.Flag.*;
+import static com.sun.c1x.graph.ScopeData.ReturnBlock.*;
+
+import java.util.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.ir.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code ScopeData} class represents inlining context when parsing the bytecodes
+ * of an inlined method.
+ *
+ * @author Ben L. Titzer
+*/
+public class ScopeData {
+    // XXX: refactor and split this class into ScopeData, JsrScopeData, and InlineScopeData
+
+    /**
+     * An enumeration of flags describing scope attributes.
+     */
+    public enum Flag {
+        /**
+         * Scope is protected by an exception handler.
+         * This attribute is inherited by nested scopes.
+         */
+        HasHandler,
+
+        /**
+         * Code in scope cannot contain safepoints.
+         * This attribute is inherited by nested scopes.
+         */
+        NoSafepoints;
+
+        public final int mask = 1 << ordinal();
+    }
+
+
+    final ScopeData parent;
+    // the IR scope
+    final IRScope scope;
+    // bci-to-block mapping
+    final BlockMap blockMap;
+    // the bytecode stream
+    final BytecodeStream stream;
+    // the constant pool
+    final RiConstantPool constantPool;
+    // the worklist of blocks, managed like a sorted list
+    BlockBegin[] workList;
+    // the current position in the worklist
+    int workListIndex;
+    // maximum inline size for this scope
+    int maxInlineSize;
+
+    /**
+     * Mask of {@link Flag} values.
+     */
+    int flags;
+
+    // Exception handler list
+    List<ExceptionHandler> exceptionHandlers;
+
+    // The continuation point for the inline. Currently only used in
+    // multi-block inlines, but eventually would like to use this for
+    // all inlines for uniformity and simplicity; in this case would
+    // get the continuation point from the BlockList instead of
+    // fabricating it anew because Invokes would be considered to be
+    // BlockEnds.
+    BlockBegin continuation;
+
+    // Without return value of inlined method on stack
+    FrameState continuationState;
+
+    /**
+     * Field used to generate fewer blocks when inlining. If this value is {@code null},
+     * then no {@code return}s have been encountered during inlining. If it is an instance
+     * of {@link ReturnBlock}, then it is the block info for the single {@code return}
+     * encountered. Otherwise, it will be {@link ReturnBlock#MULTIPLE_RETURNS}.
+     */
+    ReturnBlock inlinedReturnBlock;
+
+    /**
+     * Tracks the destination bci of the jsr. This is (currently) only used to determine
+     * bailout conditions, since only a subset of all of the possible jsr-ret control
+     * structures can (currently) be compiled.
+     *
+     * A value > 0 for this field indicates parsing of a jsr.
+     */
+    final int jsrEntryBci;
+
+    // We need to track the local variable in which the return address
+    // was stored to ensure we can handle inlining the jsr, because we
+    // don't handle arbitrary jsr/ret constructs.
+    int jsrRetAddrLocal;
+
+    // If we are parsing a jsr, the continuation point for rets
+    BlockBegin jsrContinuation;
+
+    final BlockBegin[] jsrDuplicatedBlocks; // blocks that have been duplicated for JSR inlining
+
+    /**
+     * Constructs a new ScopeData instance with the specified parent ScopeData.
+     * @param parent the parent scope data
+     * @param scope the IR scope
+     * @param blockMap the block map for this scope
+     * @param stream the bytecode stream
+     * @param constantPool the constant pool
+     */
+    public ScopeData(ScopeData parent, IRScope scope, BlockMap blockMap, BytecodeStream stream, RiConstantPool constantPool) {
+        this.parent = parent;
+        this.scope = scope;
+        this.blockMap = blockMap;
+        this.stream = stream;
+        this.constantPool = constantPool;
+        this.jsrEntryBci = -1;
+        this.jsrDuplicatedBlocks = null;
+        if (parent != null) {
+            maxInlineSize = (int) (C1XOptions.MaximumInlineRatio * parent.maxInlineSize());
+            if (maxInlineSize < C1XOptions.MaximumTrivialSize) {
+                maxInlineSize = C1XOptions.MaximumTrivialSize;
+            }
+            if (parent.hasHandler()) {
+                flags |= HasHandler.mask;
+            }
+            if (parent.noSafepoints() || scope.method.noSafepoints()) {
+                flags |= NoSafepoints.mask;
+            }
+        } else {
+            maxInlineSize = C1XOptions.MaximumInlineSize;
+            if (scope.method.noSafepoints()) {
+                flags |= NoSafepoints.mask;
+            }
+        }
+        RiExceptionHandler[] handlers = scope.method.exceptionHandlers();
+        if (handlers != null && handlers.length > 0) {
+            exceptionHandlers = new ArrayList<ExceptionHandler>(handlers.length);
+            for (RiExceptionHandler ch : handlers) {
+                ExceptionHandler h = new ExceptionHandler(ch);
+                h.setEntryBlock(blockAt(h.handler.handlerBCI()));
+                exceptionHandlers.add(h);
+            }
+            flags |= HasHandler.mask;
+        }
+    }
+
+    /**
+     * Constructs a new ScopeData instance with the specified parent ScopeData. This constructor variant creates
+     * a scope data for parsing a JSR.
+     * @param parent the parent scope data
+     * @param scope the IR scope
+     * @param blockMap the block map for this scope
+     * @param stream the bytecode stream
+     * @param constantPool the constant pool
+     * @param jsrEntryBci the bytecode index of the entrypoint of the JSR
+     */
+    public ScopeData(ScopeData parent, IRScope scope, BlockMap blockMap, BytecodeStream stream, RiConstantPool constantPool, int jsrEntryBci) {
+        this.parent = parent;
+        this.scope = scope;
+        this.blockMap = blockMap;
+        this.stream = stream;
+        this.constantPool = constantPool;
+        assert jsrEntryBci > 0 : "jsr cannot jump to BCI 0";
+        assert parent != null : "jsr must have parent scope";
+        this.jsrEntryBci = jsrEntryBci;
+        this.jsrDuplicatedBlocks = new BlockBegin[scope.method.code().length];
+        this.jsrRetAddrLocal = -1;
+
+        maxInlineSize = (int) (C1XOptions.MaximumInlineRatio * parent.maxInlineSize());
+        if (maxInlineSize < C1XOptions.MaximumTrivialSize) {
+            maxInlineSize = C1XOptions.MaximumTrivialSize;
+        }
+        flags = parent.flags;
+
+        // duplicate the parent scope's exception handlers, if any
+        List<ExceptionHandler> handlers = parent.exceptionHandlers();
+        if (handlers != null && handlers.size() > 0) {
+            exceptionHandlers = new ArrayList<ExceptionHandler>(handlers.size());
+            for (ExceptionHandler ph : handlers) {
+                ExceptionHandler h = new ExceptionHandler(ph);
+                int handlerBci = h.handler.handlerBCI();
+                if (handlerBci >= 0) {
+                    // need to duplicate the handler block because it is a "normal" handler
+                    h.setEntryBlock(blockAt(handlerBci));
+                } else {
+                    // don't duplicate the handler block because it is a synchronization handler
+                    // that was added by parsing/inlining a synchronized method
+                    assert ph.entryBlock().checkBlockFlag(BlockBegin.BlockFlag.DefaultExceptionHandler);
+                    h.setEntryBlock(ph.entryBlock());
+                }
+                exceptionHandlers.add(h);
+            }
+            assert hasHandler();
+        }
+    }
+
+    /**
+     * Gets the block beginning at the specified bytecode index. Note that this method
+     * will clone the block if it the scope data is currently parsing a JSR.
+     * @param bci the bytecode index of the start of the block
+     * @return the block starting at the specified bytecode index
+     */
+    public BlockBegin blockAt(int bci) {
+        if (jsrDuplicatedBlocks != null) {
+            // all blocks in a JSR are duplicated on demand using an internal array,
+            // including those for exception handlers in the scope of the method
+            // containing the jsr (because those exception handlers may contain ret
+            // instructions in some cases).
+            BlockBegin block = jsrDuplicatedBlocks[bci];
+            if (block == null) {
+                BlockBegin p = this.parent.blockAt(bci);
+                if (p != null) {
+                    BlockBegin newBlock = new BlockBegin(p.bci(), C1XCompilation.compilation().hir().nextBlockNumber());
+                    newBlock.setDepthFirstNumber(p.depthFirstNumber());
+                    newBlock.copyBlockFlags(p);
+                    jsrDuplicatedBlocks[bci] = newBlock;
+                    block = newBlock;
+                }
+            }
+            return block;
+        }
+        return blockMap.get(bci);
+    }
+
+    /**
+     * Checks whether this scope has any handlers.
+     * @return {@code true} if there are any exception handlers
+     */
+    public boolean hasHandler() {
+        return (flags & Flag.HasHandler.mask) != 0;
+    }
+
+    /**
+     * Checks whether this scope can contain safepoints.
+     */
+    public boolean noSafepoints() {
+        return (flags & Flag.NoSafepoints.mask) != 0;
+    }
+
+    /**
+     * Gets the maximum inline size.
+     * @return the maximum inline size
+     */
+    public int maxInlineSize() {
+        return maxInlineSize;
+    }
+
+    /**
+     * Gets the size of the stack at the caller.
+     * @return the size of the stack
+     */
+    public int callerStackSize() {
+        FrameState state = scope.callerState;
+        return state == null ? 0 : state.stackSize();
+    }
+
+    /**
+     * Gets the block continuation for this ScopeData.
+     * @return the continuation
+     */
+    public BlockBegin continuation() {
+        return continuation;
+    }
+
+    /**
+     * Sets the continuation for this ScopeData.
+     * @param continuation the continuation
+     */
+    public void setContinuation(BlockBegin continuation) {
+        this.continuation = continuation;
+    }
+
+    /**
+     * Gets the state at the continuation point.
+     * @return the state at the continuation point
+     */
+    public FrameState continuationState() {
+        return continuationState;
+    }
+
+    /**
+     * Sets the state at the continuation point.
+     * @param state the state at the continuation
+     */
+    public void setContinuationState(FrameState state) {
+        continuationState = state;
+    }
+
+    /**
+     * Checks whether this ScopeData is parsing a JSR.
+     * @return {@code true} if this scope data is parsing a JSR
+     */
+    public boolean parsingJsr() {
+        return jsrEntryBci > 0;
+    }
+
+    /**
+     * Gets the bytecode index for the JSR entry.
+     * @return the jsr entry bci
+     */
+    public int jsrEntryBCI() {
+        return jsrEntryBci;
+    }
+
+    /**
+     * Gets the index of the local variable containing the JSR return address.
+     * @return the index of the local with the JSR return address
+     */
+    public int jsrEntryReturnAddressLocal() {
+        return jsrRetAddrLocal;
+    }
+
+    /**
+     * Sets the index of the local variable containing the JSR return address.
+     * @param local the local
+     */
+    public void setJsrEntryReturnAddressLocal(int local) {
+        jsrRetAddrLocal = local;
+    }
+
+    /**
+     * Gets the continuation for parsing a JSR.
+     * @return the jsr continuation
+     */
+    public BlockBegin jsrContinuation() {
+        return jsrContinuation;
+    }
+
+    /**
+     * Sets the continuation for parsing a JSR.
+     * @param block the block that is the continuation
+     */
+    public void setJsrContinuation(BlockBegin block) {
+        jsrContinuation = block;
+    }
+
+    /**
+     * A block delimited by a return instruction in an inlined method.
+     */
+    public static class ReturnBlock {
+        /**
+         * The inlined block.
+         */
+        final BlockBegin block;
+
+        /**
+         * The second last instruction in the block. That is, the one before the return instruction.
+         */
+        final Instruction returnPredecessor;
+
+        /**
+         * The frame state at the end of the block.
+         */
+        final FrameState returnState;
+
+        ReturnBlock(BlockBegin block, Instruction returnPredecessor, FrameState returnState) {
+            super();
+            this.block = block;
+            this.returnPredecessor = returnPredecessor;
+            this.returnState = returnState;
+        }
+
+        public static final ReturnBlock MULTIPLE_RETURNS = new ReturnBlock(null, null, null);
+    }
+
+    /**
+     * Updates the info about blocks in this scope delimited by a return instruction.
+     *
+     * @param block a block delimited by a {@code return} instruction
+     * @param returnPredecessor the second last instruction in the block. That is, the one before the return instruction.
+     * @param returnState the frame state after the return instruction
+     */
+    public void updateSimpleInlineInfo(BlockBegin block, Instruction returnPredecessor, FrameState returnState) {
+        if (inlinedReturnBlock == null) {
+            inlinedReturnBlock = new ReturnBlock(block, returnPredecessor, returnState);
+        } else {
+            inlinedReturnBlock = MULTIPLE_RETURNS;
+        }
+    }
+
+    /**
+     * Gets the return block info for a simple inline scope. That is, a scope that contains only a
+     * single block delimited by a {@code return} instruction.
+     *
+     * @return the return block info for a simple inline scope or {@code null} if this is not a simple inline scope
+     */
+    public ReturnBlock simpleInlineInfo() {
+        if (inlinedReturnBlock == MULTIPLE_RETURNS) {
+            return null;
+        }
+        return inlinedReturnBlock;
+    }
+
+    /**
+     * Gets the list of exception handlers for this scope data.
+     * @return the list of exception handlers
+     */
+    public List<ExceptionHandler> exceptionHandlers() {
+        return exceptionHandlers;
+    }
+
+    /**
+     * Adds an exception handler to this scope data.
+     * @param handler the handler to add
+     */
+    public void addExceptionHandler(ExceptionHandler handler) {
+        if (exceptionHandlers == null) {
+            exceptionHandlers = new ArrayList<ExceptionHandler>();
+        }
+        assert !parsingJsr() : "jsr scope should already have all the handlers it needs";
+        exceptionHandlers.add(handler);
+        flags |= HasHandler.mask;
+    }
+
+    /**
+     * 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
+     */
+    public void addToWorkList(BlockBegin block) {
+        if (!block.isOnWorkList()) {
+            if (block == continuation || block == jsrContinuation) {
+                return;
+            }
+            block.setOnWorkList(true);
+            sortIntoWorkList(block);
+        }
+    }
+
+    private void sortIntoWorkList(BlockBegin top) {
+        // XXX: this is O(n), since the whole list is sorted; a heap could achieve O(nlogn), but
+        //      would only pay off for large worklists
+        if (workList == null) {
+            // need to allocate the worklist
+            workList = new BlockBegin[5];
+        } else if (workListIndex == workList.length) {
+            // need to grow the worklist
+            BlockBegin[] nworkList = new BlockBegin[workList.length * 3];
+            System.arraycopy(workList, 0, nworkList, 0, workList.length);
+            workList = nworkList;
+        }
+        // put the block at the end of the array
+        workList[workListIndex++] = top;
+        int dfn = top.depthFirstNumber();
+        assert dfn >= 0 : top + " does not have a depth first number";
+        int i = workListIndex - 2;
+        // push top towards the beginning of the array
+        for (; i >= 0; i--) {
+            BlockBegin b = workList[i];
+            if (b.depthFirstNumber() >= dfn) {
+                break; // already in the right position
+            }
+            workList[i + 1] = b; // bubble b down by one
+            workList[i] = top;   // and overwrite it with 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
+     */
+    public BlockBegin removeFromWorkList() {
+        if (workListIndex == 0) {
+            return null;
+        }
+        // pop the last item off the end
+        return workList[--workListIndex];
+    }
+
+    /**
+     * Converts this scope data to a string for debugging purposes.
+     * @return a string representation of this scope data
+     */
+    @Override
+    public String toString() {
+        if (parsingJsr()) {
+            return "jsr@" + jsrEntryBci + " data for " + scope.toString();
+        } else {
+            return "data for " + scope.toString();
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/graph/package-info.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,153 @@
+/*
+ * 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.sun.c1x.graph.IR} class drives the generation of the HIR graph for a method, making use of other
+ * utility classes in this package.
+ *
+ * The graph building is separated into a basic build phase ({@link com.sun.c1x.graph.IR#buildGraph} method)and
+ * (currently) two optimization phases ({@link com.sun.c1x.graph.IR#optimize1} and
+ * {@link com.sun.c1x.graph.IR#optimize2}) although the basic phase also does some (basic) optimizations.
+ *
+ * <H2>Basic Graph Build Phase</H2>
+ *
+ * {@code IR.buildGraph} creates an {@link com.sun.c1x.ir.IRScope topScope} object,
+ * that represents a context for inlining, and then invokes the constructor for the
+ * {@link com.sun.c1x.graph.GraphBuilder} class, passing the {@link com.sun.c1x.C1XCompilation}, and {@code IR}
+ * instances, which are cached. The following support objects are created in the constructor:
+ *
+ * <ul>
+ * <li>{@code memoryMap}: an instance of {@link com.sun.c1x.graph.MemoryMap}
+ * <li>{@code localValueMap}: an instance of {@link com.sun.c1x.opt.ValueMap}
+ * <li>{@code canonicalizer}: an instance of {@link com.sun.c1x.opt.Canonicalizer}
+ * </ul>
+ *
+ * Now the {@link com.sun.c1x.graph.GraphBuilder#build} is invoked with {@code topScope} as argument.
+ *
+ * <H3>{@code GraphBuilder.build}</H3>
+ *
+ * <ol>
+ * <li>The {@link com.sun.c1x.graph.IR#startBlock} field of the cached {@link com.sun.c1x.graph.IR} instance is set to a newly created
+ * {@link com.sun.c1x.ir.BlockBegin} node, with bytecode index 0 and then the {@link com.sun.c1x.graph.BlockMap} is
+ * constructed by calling {@link com.sun.c1x.C1XCompilation#getBlockMap}. This behaves slightly differently depending on
+ * whether this is an OSR compilation. If so, a new {@link com.sun.c1x.ir.BlockBegin} node is added to the map at the OSR bytecode
+ * index. The map is then built by the{@link com.sun.c1x.graph.BlockMap#build}, which takes a boolean argument that
+ * controls whether a second pass is made over the bytecodes to compute stores in loops. This always false for an OSR
+ * compilation (why?). Otherwise, it is only true if enabled by the {@link com.sun.c1x.C1XOptions#PhiLoopStores}
+ * compilation option. FInally some unneeded state from the map is removed by the {@link com.sun.c1x.graph.BlockMap#cleanup} method, and
+ * the statistics are updated.
+ * </li>
+ *
+ * <li>Next the {@link com.sun.c1x.graph.GraphBuilder#pushRootScope} method is called, with the passed-in {@link com.sun.c1x.ir.IRScope}
+ * object, the {@link com.sun.c1x.graph.BlockMap} returned by build and the {@code startBlock}. (Note: Unlike
+ * {@link com.sun.c1x.graph.GraphBuilder#pushScope}, this method does not propagate the
+ * {@link com.sun.c1x.graph.BlockMap#storesInLoops} field to the {@link com.sun.c1x.ir.IRScope} object, which means that
+ * {@link com.sun.c1x.ir.BlockBegin#insertLoopPhis} will always get null for this value. Is this a bug?).
+ * {@link com.sun.c1x.graph.GraphBuilder#pushRootScope} initializes the {@link com.sun.c1x.graph.GraphBuilder#scopeData} field with a
+ * {@link com.sun.c1x.graph.ScopeData} instance, with null parent. The
+ * {@link com.sun.c1x.graph.GraphBuilder#compilation} instance is called to get an {@link com.sun.cri.ri.RiConstantPool}
+ * , which is C1X's interface to constant pool information. The {@link com.sun.c1x.graph.GraphBuilder#curBlock} field is
+ * set to the {@code startBlock}.
+ * <p>
+ *
+ * Now a {@link com.sun.c1x.value.FrameState initialState} object is created by
+ * {@link com.sun.c1x.graph.GraphBuilder#stateAtEntry}. If the method is not static, then a {@link com.sun.c1x.ir.Local}
+ * instance is created at index 0. Since the receiver cannot be {@code null}, the
+ * {@link com.sun.c1x.ir.Value.Flag#NonNull} flag is set. Additional {@link com.sun.c1x.ir.Local} instances are created for the
+ * arguments to the method. The index is incremented by the number of slots occupied by the
+ * {@link com.sun.cri.ci.CiKind} corresponding to the argument type. All the {@link com.sun.c1x.ir.Local} instances are stored in the
+ * {@link com.sun.c1x.value.FrameState} using the {@link com.sun.c1x.value.FrameState#storeLocal} method. This {@link com.sun.c1x.value.FrameState} is then
+ * merged into the {@link com.sun.c1x.ir.BlockBegin#stateBefore} for the {@code startBlock}, which just results in a
+ * copy since {@code stateBefore} will be {@code null}.
+ * </li>
+ * <li>
+ * This step sets up three instance fields: {@link com.sun.c1x.graph.GraphBuilder#curBlock} and
+ * {@link com.sun.c1x.graph.GraphBuilder#lastInstr} to {@code startBlock} and
+ * {@link com.sun.c1x.graph.GraphBuilder#curState} to {@code initialState}. (N.B. the setting of {@code curBlock} is
+ * redundant as it is done in {@link com.sun.c1x.graph.GraphBuilder#pushRootScope}).
+ * </li>
+ * <li>
+ * Step 4 contains special handling for synchronized methods (TBD), otherwise it calls
+ * {@link com.sun.c1x.graph.GraphBuilder#finishStartBlock} which adds a {@link com.sun.c1x.ir.Base} block as the end of
+ * the {@code startBlock}. The {@link com.sun.c1x.ir.Base} block has one successor set to the (entry) block with flag
+ * {@link com.sun.c1x.ir.BlockBegin.BlockFlag#StandardEntry}, that was created by {@link com.sun.c1x.graph.BlockMap#build} (and possibly a
+ * successor to an OSREntry block).
+ * </li>
+ * <li>
+ * Then the {@link com.sun.c1x.ir.IRScope#lockStackSize} is computed. (TBD)
+ * </li>
+ * <li>
+ * Then the method is checked for being intrinsic, i.e., one that has a hard-wired implementation known to C1X. If so,
+ * and {@link com.sun.c1x.C1XOptions#OptIntrinsify} is set, an attempt is made to inline it (TBD). Otherwise, or if the
+ * intrinsification fails, normal processing continues by adding the entry block to the
+ * {@link com.sun.c1x.graph.ScopeData} work list (kept topologically sorted) and calling
+ * {@link com.sun.c1x.graph.GraphBuilder#iterateAllBlocks}.
+ * </li>
+ * <li>
+ * Finally there is some cleanup code for synchronized blocks and OSR compilations.
+ * </li>
+ * </ol>
+ *
+ * <H3>{@link com.sun.c1x.graph.GraphBuilder#iterateAllBlocks}</H3>
+ * {@link com.sun.c1x.graph#iterateAllBlocks} repeatedly removes a block from the work list and, if not already visited, marks it so,
+ * kills the current memory map, sets {@link com.sun.c1x.graph.GraphBuilder#curBlock}, {@link com.sun.c1x.graph.GraphBuilder#curState} and {@link com.sun.c1x.graph.GraphBuilder#lastInstr} and then calls
+ * {@link com.sun.c1x.graph.GraphBuilder#iterateBytecodesForBlock}.
+ *
+ * This process continues until all the blocks have been visited (processed) after which control returns to {@code
+ * build}.
+ * <p>
+
+ * <H3>{@link com.sun.c1x.graph.GraphBuilder#iterateBytecodesForBlock}</H3>
+ *
+ * {@link com.sun.c1x.graph.GraphBuilder#iterateBytecodesForBlock} performs an abstract interpretation of the bytecodes in the block, appending new
+ * nodes as necessary, until the last added node is an instance of {@link com.sun.c1x.ir.BlockEnd}. (Note: It has an
+ * explicit check for finding a new {@link com.sun.c1x.ir.BlockBegin} before a {@link com.sun.c1x.ir.BlockEnd} but
+ * {@link com.sun.c1x.graph.BlockMap#moveSuccessorLists} has a similar check so this may be redundant). For example,
+ * consider the following bytecodes:
+ *
+ * <pre>
+ * <code>
+ *         0: iconst_0
+ *         1: istore_2
+ *         2: goto 22
+ * </code>
+ * </pre>
+ *
+ * The {@code iconst_0} bytecode causes a {@link com.sun.c1x.ir.Constant} node representing zero to be pushed on the
+ * {@link com.sun.c1x.graph.GraphBuilder#curState} stack and the node to be appended to the {@link com.sun.c1x.ir.BlockBegin} (entry) node associated with index 0.
+ * The {@code istore_2} causes the node to be popped of the stack and stored in the local slot 2. No IR node is
+ * generated for the {@code istore_2}. The {@code goto} creates a {@link com.sun.c1x.ir.Goto} node which is a subclass
+ * of {@link com.sun.c1x.ir.BlockEnd}, so this terminates the iteration. As part of termination the {@link com.sun.c1x.ir.Goto} node is marked as the
+ * end node of the current block and the {@link com.sun.c1x.value.FrameState} is propagated to the successor node(s) by merging any
+ * existing {@link com.sun.c1x.value.FrameState} with the current state. If the target is a loop header node this involves inserting
+ * {@link com.sun.c1x.ir.Phi} nodes. Finally, the target node is added to the {@code scopeData} work list.
+ * <p>
+ *
+ *
+ * @author Ben Titzer
+ * @author Mick Jordan
+ *
+ */
+package com.sun.c1x.graph;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/AccessArray.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,73 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+
+/**
+ * This the base class of all array operations.
+ *
+ * @author Ben L. Titzer
+ */
+public abstract class AccessArray extends StateSplit {
+
+    protected Value array;
+
+    /**
+     * 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 stateBefore the frame state before the instruction
+     */
+    public AccessArray(CiKind kind, Value array, FrameState stateBefore) {
+        super(kind, stateBefore);
+        this.array = array;
+        if (array.isNonNull()) {
+            eliminateNullCheck();
+        }
+    }
+
+    /**
+     * Gets the instruction that produces the array object.
+     * @return the instruction that produces the array object
+     */
+    public Value array() {
+        return array;
+    }
+
+    /**
+     * Clears the state if this instruction can (no longer) trap.
+     */
+    @Override
+    public void runtimeCheckCleared() {
+        if (!canTrap()) {
+            clearState();
+        }
+    }
+
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        array = closure.apply(array);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/AccessField.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,138 @@
+/*
+ * 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.sun.c1x.ir;
+
+import java.lang.reflect.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The base class of all instructions that access fields.
+ *
+ * @author Ben L. Titzer
+ */
+public abstract class AccessField extends StateSplit {
+
+    private Value object;
+    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 isStatic indicates if the field is static
+     * @param stateBefore the state before the field access
+     * @param isLoaded indicates if the class is loaded
+     */
+    public AccessField(CiKind kind, Value object, RiField field, boolean isStatic, FrameState stateBefore, boolean isLoaded) {
+        super(kind, stateBefore);
+        this.object = object;
+        this.field = field;
+        if (!isLoaded || (C1XOptions.TestPatching && !Modifier.isVolatile(field.accessFlags()))) {
+            // require patching if the field is not loaded (i.e. resolved),
+            // or if patch testing is turned on (but not if the field is volatile)
+            setFlag(Flag.NeedsPatching);
+        }
+        initFlag(Flag.IsLoaded, isLoaded);
+        initFlag(Flag.IsStatic, isStatic);
+        if (isLoaded && object.isNonNull()) {
+            eliminateNullCheck();
+        }
+        assert object != null : "every field access must reference some object";
+    }
+
+    /**
+     * Gets the instruction that produces the receiver object of this field access
+     * (for instance field accesses).
+     * @return the instruction that produces the receiver object
+     */
+    public Value object() {
+        return object;
+    }
+
+    /**
+     * 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 checkFlag(Flag.IsStatic);
+    }
+
+    /**
+     * Checks whether the class of the field of this access is loaded.
+     * @return {@code true} if the class is loaded
+     */
+    public boolean isLoaded() {
+        return checkFlag(Flag.IsLoaded);
+    }
+
+    /**
+     * Checks whether this field is declared volatile.
+     * @return {@code true} if the field is resolved and declared volatile
+     */
+    public boolean isVolatile() {
+        return isLoaded() && Modifier.isVolatile(field.accessFlags());
+    }
+
+    @Override
+    public void runtimeCheckCleared() {
+        if (isLoaded()) {
+            clearState();
+        }
+    }
+
+    /**
+     * Checks whether this field access will require patching.
+     * @return {@code true} if this field access will require patching
+     */
+    public boolean needsPatching() {
+        return checkFlag(Flag.NeedsPatching);
+    }
+
+    /**
+     * Checks whether this field access may cause a trap or an exception, which
+     * is if it either requires a null check or needs patching.
+     * @return {@code true} if this field access can cause a trap
+     */
+    @Override
+    public boolean canTrap() {
+        return needsPatching() || needsNullCheck();
+    }
+
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        object = closure.apply(object);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/AccessIndexed.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,111 @@
+/*
+ * 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.sun.c1x.ir;
+
+import static com.sun.c1x.ir.Value.Flag.*;
+
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code AccessIndexed} class is the base class of instructions that read or write
+ * elements of an array.
+ *
+ * @author Ben L. Titzer
+ */
+public abstract class AccessIndexed extends AccessArray {
+
+    private Value index;
+    private Value length;
+    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 elementType the type of the elements of the array
+     * @param stateBefore the state before executing this instruction
+     */
+    AccessIndexed(CiKind kind, Value array, Value index, Value length, CiKind elementType, FrameState stateBefore) {
+        super(kind, array, stateBefore);
+        this.index = index;
+        this.length = length;
+        this.elementType = elementType;
+    }
+
+    /**
+     * Gets the instruction producing the index into the array.
+     * @return the index
+     */
+    public Value index() {
+        return index;
+    }
+
+    /**
+     * Gets the instruction that produces the length of the array.
+     * @return the length
+     */
+    public Value length() {
+        return length;
+    }
+
+    /**
+     * Gets the element type of the array.
+     * @return the element type
+     */
+    public CiKind elementKind() {
+        return elementType;
+    }
+
+    /**
+     * Checks whether this instruction needs a bounds check.
+     * @return {@code true} if a bounds check is needed
+     */
+    public boolean needsBoundsCheck() {
+        return !checkFlag(NoBoundsCheck);
+    }
+
+    public void eliminateBoundsCheck() {
+        clearRuntimeCheck(NoBoundsCheck);
+    }
+
+    /**
+     * Checks whether this instruction can cause a trap.
+     * @return {@code true} if this instruction can cause a trap
+     */
+    @Override
+    public boolean canTrap() {
+        return needsNullCheck() || needsBoundsCheck();
+    }
+
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        super.inputValuesDo(closure);
+        index = closure.apply(index);
+        if (length != null) {
+            length = closure.apply(length);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/AccessMonitor.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,87 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code AccessMonitor} instruction is the base class of both monitor acquisition and release.
+ *
+ * @author Ben L. Titzer
+ */
+public abstract class AccessMonitor extends StateSplit {
+
+    /**
+     * The object locked or unlocked by this instruction.
+     */
+    private Value object;
+
+    /**
+     * The address of the on-stack lock object or {@code null} if the runtime does not place locks on the stack.
+     */
+    private Value lockAddress;
+
+    /**
+     * 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 stateBefore the state before executing the monitor operation
+     * @param lockNumber the number of the lock being acquired
+     */
+    public AccessMonitor(Value object, Value lockAddress, FrameState stateBefore, int lockNumber) {
+        super(CiKind.Illegal, stateBefore);
+        this.object = object;
+        this.lockAddress = lockAddress;
+        this.lockNumber = lockNumber;
+    }
+
+    /**
+     * Gets the instruction producing the object locked or unlocked by this instruction.
+     */
+    public Value object() {
+        return object;
+    }
+
+    /**
+     * Gets the instruction producing the address of the lock object.
+     */
+    public Value lockAddress() {
+        return lockAddress;
+    }
+
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        object = closure.apply(object);
+        if (lockAddress != null) {
+            lockAddress = closure.apply(lockAddress);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/ArithmeticOp.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.ir;
+
+import com.sun.c1x.*;
+import com.sun.c1x.debug.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code ArithmeticOp} class represents arithmetic operations such as addition, subtraction, etc.
+ *
+ * @author Ben L. Titzer
+ */
+public final class ArithmeticOp extends Op2 {
+
+    private FrameState stateBefore;
+
+    /**
+     * 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
+     * @param stateBefore the state for instructions that may trap
+     */
+    public ArithmeticOp(int opcode, CiKind kind, Value x, Value y, boolean isStrictFP, FrameState stateBefore) {
+        super(kind, opcode, x, y);
+        initFlag(Flag.IsStrictFP, isStrictFP);
+        if (stateBefore != null) {
+            // state before is only used in the case of a division or remainder,
+            // and isn't needed if the zero check is redundant
+            if (y.isConstant()) {
+                long divisor = y.asConstant().asLong();
+                if (divisor != 0) {
+                    C1XMetrics.ZeroChecksRedundant++;
+                    setFlag(Flag.NoZeroCheck);
+                } else {
+                    this.stateBefore = stateBefore;
+                }
+                if (divisor != -1) {
+                    C1XMetrics.DivideSpecialChecksRedundant++;
+                    setFlag(Flag.NoDivSpecialCase);
+                }
+            } else {
+                this.stateBefore = stateBefore;
+            }
+        }
+    }
+
+    @Override
+    public FrameState stateBefore() {
+        return stateBefore;
+    }
+
+    /**
+     * Checks whether this instruction has strict fp semantics.
+     * @return {@code true} if this instruction has strict fp semantics
+     */
+    public boolean isStrictFP() {
+        return checkFlag(Flag.IsStrictFP);
+    }
+
+    /**
+     * Checks whether this instruction can cause a trap. For arithmetic operations,
+     * only division and remainder operations can cause traps.
+     * @return {@code true} if this instruction can cause a trap
+     */
+    @Override
+    public boolean canTrap() {
+        return stateBefore != null;
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitArithmeticOp(this);
+    }
+
+    public boolean isCommutative() {
+        return Bytecodes.isCommutative(opcode);
+    }
+
+    public boolean needsZeroCheck() {
+        return !checkFlag(Flag.NoZeroCheck);
+    }
+
+    public void eliminateZeroCheck() {
+        clearRuntimeCheck(Flag.NoZeroCheck);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(x()).
+             print(' ').
+             print(Bytecodes.operator(opcode)).
+             print(' ').
+             print(y());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/ArrayCopy.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * Copies a sequence of elements from a source into a destination array.
+ *
+ * @author Thomas Wuerthinger
+ *
+ */
+public class ArrayCopy extends StateSplit {
+
+    private Value src;
+    private Value srcPos;
+    private Value dest;
+    private Value destPos;
+    private Value length;
+    public final RiMethod arrayCopyMethod;
+
+    public ArrayCopy(Value src, Value srcPos, Value dest, Value destPos, Value length, RiMethod arrayCopyMethod, FrameState stateBefore) {
+        super(CiKind.Void, stateBefore);
+        this.arrayCopyMethod = arrayCopyMethod;
+        this.src = src;
+        this.srcPos = srcPos;
+        this.dest = dest;
+        this.destPos = destPos;
+        this.length = length;
+    }
+
+    public Value src() {
+        return src;
+    }
+
+    public Value srcPos() {
+        return srcPos;
+    }
+
+    public Value dest() {
+        return dest;
+    }
+
+    public Value destPos() {
+        return destPos;
+    }
+
+    public Value length() {
+        return length;
+    }
+
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        src = closure.apply(src);
+        srcPos = closure.apply(srcPos);
+        dest = closure.apply(dest);
+        destPos = closure.apply(destPos);
+        length = closure.apply(length);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitArrayCopy(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("arrayCopy ").print(src).print(" ").print(srcPos).print(" ");
+        out.print(dest).print(" ").print(destPos).print(" ").print(length);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/ArrayLength.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.util.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code ArrayLength} instruction gets the length of an array.
+ *
+ * @author Ben L. Titzer
+ */
+public final class ArrayLength extends AccessArray {
+
+    /**
+     * Constructs a new ArrayLength instruction.
+     * @param array the instruction producing the array
+     * @param newFrameState the state before executing this instruction
+     */
+    public ArrayLength(Value array, FrameState newFrameState) {
+        super(CiKind.Int, array, newFrameState);
+        if (array.isNonNull()) {
+            eliminateNullCheck();
+        }
+    }
+
+    /**
+     * Clears the state associated with a null check.
+     */
+    @Override
+    public void runtimeCheckCleared() {
+        if (!needsNullCheck()) {
+            clearState();
+        }
+    }
+
+    /**
+     * Checks whether this instruction can cause a trap.
+     * @return {@code true} if this instruction can cause a trap
+     */
+    @Override
+    public boolean canTrap() {
+        return needsNullCheck();
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitArrayLength(this);
+    }
+
+    @Override
+    public int valueNumber() {
+        return Util.hash1(Bytecodes.ARRAYLENGTH, array);
+    }
+
+    @Override
+    public boolean valueEqual(Instruction i) {
+        if (i instanceof ArrayLength) {
+            ArrayLength o = (ArrayLength) i;
+            return array == o.array;
+        }
+        return false;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(array).print(".length");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/Base.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,79 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code Base} instruction represents the end of the entry block of the procedure that has
+ * both the standard entry and the OSR entry as successors.
+ *
+ * @author Ben L. Titzer
+ */
+public final class Base extends BlockEnd {
+
+    /**
+     * Constructs a new Base instruction.
+     * @param standardEntry the standard entrypoint block
+     * @param osrEntry the OSR entrypoint block
+     */
+    public Base(BlockBegin standardEntry, BlockBegin osrEntry) {
+        super(CiKind.Illegal, null, false);
+        assert osrEntry == null || osrEntry.isOsrEntry();
+        assert standardEntry.isStandardEntry();
+        if (osrEntry != null) {
+            successors.add(osrEntry);
+        }
+        successors.add(standardEntry);
+    }
+
+    /**
+     * Gets the standard entrypoint block.
+     * @return the standard entrypoint block
+     */
+    public BlockBegin standardEntry() {
+        return defaultSuccessor();
+    }
+
+    /**
+     * Gets the OSR entrypoint block, if it exists.
+     * @return the OSR entrypoint bock, if it exists; {@code null} otherwise
+     */
+    public BlockBegin osrEntry() {
+        return successors.size() < 2 ? null : successors.get(0);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitBase(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("std entry B").print(standardEntry().blockID);
+        if (successors().size() > 1) {
+            out.print(" osr entry B").print(osrEntry().blockID);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/BlockBegin.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,912 @@
+/*
+ * 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.sun.c1x.ir;
+
+import java.util.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.asm.*;
+import com.sun.c1x.debug.*;
+import com.sun.c1x.lir.*;
+import com.sun.c1x.util.*;
+import com.sun.c1x.value.*;
+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.
+ *
+ * @author Ben L. Titzer
+ */
+public final class BlockBegin extends Instruction {
+    private static final List<BlockBegin> NO_HANDLERS = Collections.emptyList();
+
+    /**
+     * An enumeration of flags for block entries indicating various things.
+     */
+    public enum BlockFlag {
+        StandardEntry,
+        OsrEntry,
+        ExceptionEntry,
+        SubroutineEntry,
+        BackwardBranchTarget,
+        IsOnWorkList,
+        WasVisited,
+        DefaultExceptionHandler,
+        ParserLoopHeader,
+        CriticalEdgeSplit,
+        LinearScanLoopHeader,
+        LinearScanLoopEnd;
+
+        public final int mask = 1 << ordinal();
+    }
+
+    /**
+     * A unique id used in tracing.
+     */
+    public final int blockID;
+
+    /**
+     * Denotes the current set of {@link BlockBegin.BlockFlag} settings.
+     */
+    private int blockFlags;
+
+    /**
+     * The frame state before execution of the first instruction in this block.
+     */
+    private FrameState stateBefore;
+
+    /**
+     * A link to the last node in the block (which contains the successors).
+     */
+    private BlockEnd end;
+
+    /**
+     * The {@link BlockBegin} nodes for which this node is a successor.
+     */
+    private final List<BlockBegin> predecessors;
+
+    private int depthFirstNumber;
+    private int linearScanNumber;
+    private int loopDepth;
+    private int loopIndex;
+
+    private BlockBegin dominator;
+    private List<BlockBegin> exceptionHandlerBlocks;
+    private List<FrameState> exceptionHandlerStates;
+
+    // LIR block
+    public LIRBlock lirBlock;
+
+    /**
+     * Constructs a new BlockBegin at the specified bytecode index.
+     * @param bci the bytecode index of the start
+     * @param blockID the ID of the block
+     */
+    public BlockBegin(int bci, int blockID) {
+        super(CiKind.Illegal);
+        this.blockID = blockID;
+        depthFirstNumber = -1;
+        linearScanNumber = -1;
+        predecessors = new ArrayList<BlockBegin>(2);
+        loopIndex = -1;
+        setBCI(bci);
+    }
+
+    /**
+     * Gets the list of predecessors of this block.
+     * @return the predecessor list
+     */
+    public List<BlockBegin> predecessors() {
+        return predecessors;
+    }
+
+    /**
+     * Gets the dominator of this block.
+     * @return the dominator block
+     */
+    public BlockBegin dominator() {
+        return dominator;
+    }
+
+    /**
+     * Sets the dominator block for this block.
+     * @param dominator the dominator for this block
+     */
+    public void setDominator(BlockBegin dominator) {
+        this.dominator = dominator;
+    }
+
+    /**
+     * Gets the depth first traversal number of this block.
+     * @return the depth first number
+     */
+    public int depthFirstNumber() {
+        return depthFirstNumber;
+    }
+
+    /**
+     * Gets the linear scan number of this block.
+     * @return the linear scan number
+     */
+    public int linearScanNumber() {
+        return linearScanNumber;
+    }
+
+    /**
+     * Gets the loop depth of this block.
+     * @return the loop depth
+     */
+    public int loopDepth() {
+        return loopDepth;
+    }
+
+    /**
+     * Gets the loop index of this block.
+     * @return the loop index
+     */
+    public int loopIndex() {
+        return loopIndex;
+    }
+
+    /**
+     * Gets the block end associated with this basic block.
+     * @return the block end
+     */
+    public BlockEnd end() {
+        return end;
+    }
+
+    /**
+     * Gets the state at the start of this block.
+     * @return the state at the start of this block
+     */
+    @Override
+    public FrameState stateBefore() {
+        return stateBefore;
+    }
+
+    /**
+     * Sets the initial state for this block.
+     * @param stateBefore the state for this block
+     */
+    public void setStateBefore(FrameState stateBefore) {
+        assert this.stateBefore == null;
+        this.stateBefore = stateBefore;
+    }
+
+    /**
+     * Gets the exception handlers that cover one or more instructions of this basic block.
+     *
+     * @return the exception handlers
+     */
+    public List<BlockBegin> exceptionHandlerBlocks() {
+        return exceptionHandlerBlocks == null ? NO_HANDLERS : exceptionHandlerBlocks;
+    }
+
+    public List<FrameState> exceptionHandlerStates() {
+        return exceptionHandlerStates;
+    }
+
+    public void setDepthFirstNumber(int depthFirstNumber) {
+        assert depthFirstNumber >= 0;
+        this.depthFirstNumber = depthFirstNumber;
+    }
+
+    public void setLinearScanNumber(int linearScanNumber) {
+        this.linearScanNumber = linearScanNumber;
+    }
+
+    public void setLoopDepth(int loopDepth) {
+        this.loopDepth = loopDepth;
+    }
+
+    public void setLoopIndex(int loopIndex) {
+        this.loopIndex = loopIndex;
+    }
+
+    /**
+     * Set the block end for this block begin. This method will
+     * reset this block's successor list and rebuild it to be equivalent
+     * to the successor list of the specified block end.
+     * @param end the new block end for this block begin
+     */
+    public void setEnd(BlockEnd end) {
+        assert end != null;
+        BlockEnd old = this.end;
+        if (old != end) {
+            if (old != null) {
+                // disconnect this block from the old end
+                old.setBegin(null);
+                // disconnect this block from its current successors
+                for (BlockBegin s : old.successors()) {
+                    s.predecessors().remove(this);
+                }
+            }
+            this.end = end;
+            end.setBegin(this);
+            for (BlockBegin s : end.successors()) {
+                s.addPredecessor(this);
+            }
+        }
+    }
+
+    /**
+     * Set a flag on this block.
+     * @param flag the flag to set
+     */
+    public void setBlockFlag(BlockFlag flag) {
+        blockFlags |= flag.mask;
+    }
+
+    /**
+     * Clear a flag on this block.
+     * @param flag the flag to clear
+     */
+    public void clearBlockFlag(BlockFlag flag) {
+        blockFlags &= ~flag.mask;
+    }
+
+    public void copyBlockFlag(BlockBegin other, BlockFlag flag) {
+        setBlockFlag(flag, other.checkBlockFlag(flag));
+    }
+
+    /**
+     * Check whether this block has the specified flag set.
+     * @param flag the flag to test
+     * @return {@code true} if this block has the flag
+     */
+    public boolean checkBlockFlag(BlockFlag flag) {
+        return (blockFlags & flag.mask) != 0;
+    }
+
+    /**
+     * 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<BlockBegin, BlockBegin>(), closure);
+    }
+
+    /**
+     * Iterate over all blocks transitively reachable from this block.
+     * @param closure the closure to apply to each block
+     * @param predecessors {@code true} if also to include this blocks predecessors
+     */
+    public void iterateAnyOrder(BlockClosure closure, boolean predecessors) {
+        IdentityHashMap<BlockBegin, BlockBegin> mark = new IdentityHashMap<BlockBegin, BlockBegin>();
+        LinkedList<BlockBegin> queue = new LinkedList<BlockBegin>();
+        queue.offer(this);
+        mark.put(this, this);
+        BlockBegin block;
+        while ((block = queue.poll()) != null) {
+            closure.apply(block);
+            queueBlocks(queue, block.exceptionHandlerBlocks(), mark);
+            queueBlocks(queue, block.end.successors(), mark);
+            queueBlocks(queue, predecessors ? block.predecessors : null, mark);
+        }
+    }
+
+    private void queueBlocks(LinkedList<BlockBegin> queue, List<BlockBegin> list, IdentityHashMap<BlockBegin, BlockBegin> mark) {
+        if (list != null) {
+            for (BlockBegin b : list) {
+                if (!mark.containsKey(b)) {
+                    queue.offer(b);
+                    mark.put(b, b);
+                }
+            }
+        }
+    }
+
+    private void iterate(IdentityHashMap<BlockBegin, BlockBegin> mark, BlockClosure closure) {
+        if (!mark.containsKey(this)) {
+            mark.put(this, this);
+            closure.apply(this);
+            BlockEnd e = end();
+            if (exceptionHandlerBlocks != null) {
+                iterateReverse(mark, closure, exceptionHandlerBlocks);
+            }
+            assert e != null : "block must have block end";
+            iterateReverse(mark, closure, e.successors());
+        }
+    }
+
+    private void iterateReverse(IdentityHashMap<BlockBegin, BlockBegin> mark, BlockClosure closure, List<BlockBegin> list) {
+        for (int i = list.size() - 1; i >= 0; i--) {
+            list.get(i).iterate(mark, closure);
+        }
+    }
+
+    /**
+     * Adds an exception handler that covers one or more instructions in this block.
+     *
+     * @param handler the entry block for the exception handler to add
+     */
+    public void addExceptionHandler(BlockBegin handler) {
+        assert handler != null && handler.checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry);
+        if (exceptionHandlerBlocks == null) {
+            exceptionHandlerBlocks = new ArrayList<BlockBegin>(3);
+            exceptionHandlerBlocks.add(handler);
+        } else if (!exceptionHandlerBlocks.contains(handler)) {
+            exceptionHandlerBlocks.add(handler);
+        }
+    }
+
+    /**
+     * Adds a frame state that merges into the exception handler whose entry is this block.
+     *
+     * @param state the frame state at an instruction that raises an exception that can be caught by the exception
+     *            handler represented by this block
+     * @return the index of {@code state} in the list of frame states merging at this block (i.e. the frames states for
+     *         all instruction throwing an exception caught by this exception handler)
+     */
+    public int addExceptionState(FrameState state) {
+        assert checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry);
+        if (exceptionHandlerStates == null) {
+            exceptionHandlerStates = new ArrayList<FrameState>(4);
+        }
+        exceptionHandlerStates.add(state);
+        return exceptionHandlerStates.size() - 1;
+    }
+
+    /**
+     * Add a predecessor to this block.
+     * @param pred the predecessor to add
+     */
+    public void addPredecessor(BlockBegin pred) {
+        predecessors.add(pred);
+    }
+
+    /**
+     * Removes all occurrences of the specified block from the predecessor list of this block.
+     * @param pred the predecessor to remove
+     */
+    public void removePredecessor(BlockBegin pred) {
+        while (predecessors.remove(pred)) {
+            // the block may appear multiple times in the list
+            // XXX: this is not very efficient, consider Util.removeAllFromList
+        }
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitBlockBegin(this);
+    }
+
+    public void mergeOrClone(FrameState newState) {
+        FrameState existingState = stateBefore;
+
+        if (existingState == null) {
+            // this is the first state for the block
+            if (wasVisited()) {
+                // this can happen for complex jsr/ret patterns; just bail out
+                throw new CiBailout("jsr/ret too complex");
+            }
+
+            // copy state because it is modified
+            newState = newState.copy();
+
+            if (C1XOptions.UseStackMapTableLiveness) {
+                // if a liveness map is available, use it to invalidate dead locals
+                CiBitMap[] livenessMap = newState.scope().method.livenessMap();
+                if (livenessMap != null && bci() >= 0) {
+                    assert bci() < livenessMap.length;
+                    CiBitMap liveness = livenessMap[bci()];
+                    if (liveness != null) {
+                        invalidateDeadLocals(newState, liveness);
+                    }
+                }
+            }
+
+            // if the block is a loop header, insert all necessary phis
+            if (isParserLoopHeader()) {
+                insertLoopPhis(newState);
+            }
+
+            stateBefore = newState;
+        } else {
+            if (!C1XOptions.AssumeVerifiedBytecode && !existingState.isSameAcrossScopes(newState)) {
+                // stacks or locks do not match--bytecodes would not verify
+                throw new CiBailout("stack or locks do not match");
+            }
+
+            // while (existingState.scope() != newState.scope()) {
+            //     // XXX: original code is not sure if this is necessary
+            //     newState = newState.scope().callerState();
+            //     assert newState != null : "could not match scopes";
+            // }
+            // above code replaced with assert for the moment
+            assert existingState.scope() == newState.scope();
+
+            assert existingState.localsSize() == newState.localsSize();
+            assert existingState.stackSize() == newState.stackSize();
+
+            if (wasVisited() && !isParserLoopHeader()) {
+                throw new CiBailout("jsr/ret too complicated");
+            }
+
+            existingState.merge(this, newState);
+        }
+    }
+
+    private void invalidateDeadLocals(FrameState newState, CiBitMap liveness) {
+        int max = newState.localsSize();
+        assert max <= liveness.size();
+        for (int i = 0; i < max; i++) {
+            Value x = newState.localAt(i);
+            if (x != null) {
+                if (!liveness.get(i)) {
+                    // invalidate the local if it is not live
+                    newState.invalidateLocal(i);
+                }
+            }
+        }
+    }
+
+    private void insertLoopPhis(FrameState newState) {
+        int stackSize = newState.stackSize();
+        for (int i = 0; i < stackSize; i++) {
+            // always insert phis for the stack
+            newState.setupPhiForStack(this, i);
+        }
+        int localsSize = newState.localsSize();
+        CiBitMap requiresPhi = newState.scope().getStoresInLoops();
+        for (int i = 0; i < localsSize; i++) {
+            Value x = newState.localAt(i);
+            if (x != null) {
+                if (requiresPhi != null) {
+                    if (requiresPhi.get(i) || x.kind.isDoubleWord() && requiresPhi.get(i + 1)) {
+                        // selectively do a phi
+                        newState.setupPhiForLocal(this, i);
+                    }
+                } else {
+                    // always setup a phi
+                    newState.setupPhiForLocal(this, i);
+                }
+            }
+        }
+    }
+
+    public boolean isStandardEntry() {
+        return checkBlockFlag(BlockFlag.StandardEntry);
+    }
+
+    public void setStandardEntry() {
+        setBlockFlag(BlockFlag.StandardEntry);
+    }
+
+    public boolean isOsrEntry() {
+        return checkBlockFlag(BlockFlag.OsrEntry);
+    }
+
+    public void setOsrEntry(boolean value) {
+        setBlockFlag(BlockFlag.OsrEntry, value);
+    }
+
+    public boolean isBackwardBranchTarget() {
+        return checkBlockFlag(BlockFlag.BackwardBranchTarget);
+    }
+
+    public void setBackwardBranchTarget(boolean value) {
+        setBlockFlag(BlockFlag.BackwardBranchTarget, value);
+    }
+
+    public boolean isCriticalEdgeSplit() {
+        return checkBlockFlag(BlockFlag.CriticalEdgeSplit);
+    }
+
+    public void setCriticalEdgeSplit(boolean value) {
+        setBlockFlag(BlockFlag.CriticalEdgeSplit, value);
+    }
+
+    public boolean isExceptionEntry() {
+        return checkBlockFlag(BlockFlag.ExceptionEntry);
+    }
+
+    public void setExceptionEntry() {
+        setBlockFlag(BlockFlag.ExceptionEntry);
+    }
+
+    public boolean isSubroutineEntry() {
+        return checkBlockFlag(BlockFlag.SubroutineEntry);
+    }
+
+    public void setSubroutineEntry() {
+        setBlockFlag(BlockFlag.SubroutineEntry);
+    }
+
+    public boolean isOnWorkList() {
+        return checkBlockFlag(BlockFlag.IsOnWorkList);
+    }
+
+    public void setOnWorkList(boolean value) {
+        setBlockFlag(BlockFlag.IsOnWorkList, value);
+    }
+
+    public boolean wasVisited() {
+        return checkBlockFlag(BlockFlag.WasVisited);
+    }
+
+    public void setWasVisited(boolean value) {
+        setBlockFlag(BlockFlag.WasVisited, value);
+    }
+
+    public boolean isParserLoopHeader() {
+        return checkBlockFlag(BlockFlag.ParserLoopHeader);
+    }
+
+    public void setParserLoopHeader(boolean value) {
+        setBlockFlag(BlockFlag.ParserLoopHeader, value);
+    }
+
+    public boolean isLinearScanLoopHeader() {
+        return checkBlockFlag(BlockFlag.LinearScanLoopHeader);
+    }
+
+    public void setLinearScanLoopHeader(boolean value) {
+        setBlockFlag(BlockFlag.LinearScanLoopHeader, value);
+    }
+
+    public boolean isLinearScanLoopEnd() {
+        return checkBlockFlag(BlockFlag.LinearScanLoopEnd);
+    }
+
+    public void setLinearScanLoopEnd(boolean value) {
+        setBlockFlag(BlockFlag.LinearScanLoopEnd, value);
+    }
+
+    private void setBlockFlag(BlockFlag flag, boolean value) {
+        if (value) {
+            setBlockFlag(flag);
+        } else {
+            clearBlockFlag(flag);
+        }
+    }
+
+    public void copyBlockFlags(BlockBegin other) {
+        copyBlockFlag(other, BlockBegin.BlockFlag.ParserLoopHeader);
+        copyBlockFlag(other, BlockBegin.BlockFlag.SubroutineEntry);
+        copyBlockFlag(other, BlockBegin.BlockFlag.ExceptionEntry);
+        copyBlockFlag(other, BlockBegin.BlockFlag.WasVisited);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("block #");
+        builder.append(blockID);
+        builder.append(",");
+        builder.append(depthFirstNumber);
+        builder.append(" @ ");
+        builder.append(bci());
+        builder.append(" [");
+        boolean hasFlag = false;
+        for (BlockFlag f : BlockFlag.values()) {
+            if (checkBlockFlag(f)) {
+                if (hasFlag) {
+                    builder.append(' ');
+                }
+                builder.append(f.name());
+                hasFlag = true;
+            }
+        }
+
+        builder.append("]");
+        if (end != null) {
+            builder.append(" -> ");
+            boolean hasSucc = false;
+            for (BlockBegin s : end.successors()) {
+                if (hasSucc) {
+                    builder.append(", ");
+                }
+                builder.append("#");
+                builder.append(s.blockID);
+                hasSucc = true;
+            }
+        }
+        return builder.toString();
+    }
+
+    /**
+     * Get the number of successors.
+     * @return the number of successors
+     */
+    public int numberOfSux() {
+        return end.successors.size();
+    }
+
+    /**
+     * Get the successor at a certain position.
+     * @param i the position
+     * @return the successor
+     */
+    public BlockBegin suxAt(int i) {
+        return end.successors.get(i);
+    }
+
+    /**
+     * Get the number of predecessors.
+     * @return the number of predecessors
+     */
+    public int numberOfPreds() {
+        return predecessors.size();
+    }
+
+    /**
+     * @return the label associated with the block, used by the LIR
+     */
+    public Label label() {
+        return lirBlock().label;
+    }
+
+    public void setLir(LIRList lir) {
+        lirBlock().setLir(lir);
+    }
+
+    public LIRList lir() {
+        return lirBlock().lir();
+    }
+
+    public LIRBlock lirBlock() {
+        if (lirBlock == null) {
+            lirBlock = new LIRBlock();
+        }
+        return lirBlock;
+    }
+
+    public int exceptionHandlerPco() {
+        return lirBlock == null ? 0 : lirBlock.exceptionHandlerPCO;
+    }
+
+    public void setExceptionHandlerPco(int codeOffset) {
+        lirBlock().exceptionHandlerPCO = codeOffset;
+    }
+
+    public int numberOfExceptionHandlers() {
+        return exceptionHandlerBlocks == null ? 0 : exceptionHandlerBlocks.size();
+    }
+
+    public BlockBegin exceptionHandlerAt(int i) {
+        return exceptionHandlerBlocks.get(i);
+    }
+
+    public BlockBegin predAt(int j) {
+        return predecessors.get(j);
+    }
+
+    public int firstLirInstructionId() {
+        return lirBlock.firstLirInstructionID;
+    }
+
+    public void setFirstLirInstructionId(int firstLirInstructionId) {
+        lirBlock.firstLirInstructionID = firstLirInstructionId;
+    }
+
+    public int lastLirInstructionId() {
+        return lirBlock.lastLirInstructionID;
+    }
+
+    public void setLastLirInstructionId(int lastLirInstructionId) {
+        lirBlock.lastLirInstructionID = lastLirInstructionId;
+    }
+
+    public boolean isPredecessor(BlockBegin block) {
+        return this.predecessors.contains(block);
+    }
+
+    public void printWithoutPhis(LogStream out) {
+        // print block id
+        BlockEnd end = end();
+        out.print("B").print(blockID).print(" ");
+
+        // print flags
+        StringBuilder sb = new StringBuilder(8);
+        if (isStandardEntry()) {
+            sb.append('S');
+        }
+        if (isOsrEntry()) {
+            sb.append('O');
+        }
+        if (isExceptionEntry()) {
+            sb.append('E');
+        }
+        if (isSubroutineEntry()) {
+            sb.append('s');
+        }
+        if (isParserLoopHeader()) {
+            sb.append("LH");
+        }
+        if (isBackwardBranchTarget()) {
+            sb.append('b');
+        }
+        if (wasVisited()) {
+            sb.append('V');
+        }
+        if (sb.length() != 0) {
+            out.print('(').print(sb.toString()).print(')');
+        }
+
+        // print block bci range
+        out.print('[').print(bci()).print(", ").print(end == null ? -1 : end.bci()).print(']');
+
+        // print block successors
+        if (end != null && end.successors().size() > 0) {
+            out.print(" .");
+            for (BlockBegin successor : end.successors()) {
+                out.print(" B").print(successor.blockID);
+            }
+        }
+        // print exception handlers
+        if (!exceptionHandlers().isEmpty()) {
+            out.print(" (xhandlers");
+            for (BlockBegin handler : exceptionHandlerBlocks()) {
+                out.print(" B").print(handler.blockID);
+            }
+            out.print(')');
+        }
+
+        // print dominator block
+        if (dominator() != null) {
+            out.print(" dom B").print(dominator().blockID);
+        }
+
+        // print predecessors
+        if (!predecessors().isEmpty()) {
+            out.print(" pred:");
+            for (BlockBegin pred : predecessors()) {
+                out.print(" B").print(pred.blockID);
+            }
+        }
+    }
+
+    @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 = stateBefore();
+
+            int i = 0;
+            while (!hasPhisOnStack && i < state.stackSize()) {
+                Value value = state.stackAt(i);
+                hasPhisOnStack = isPhiAtBlock(value);
+                if (value != null && !value.isIllegal()) {
+                    i += value.kind.sizeInSlots();
+                } else {
+                    i++;
+                }
+            }
+
+            do {
+                for (i = 0; !hasPhisInLocals && i < state.localsSize();) {
+                    Value value = state.localAt(i);
+                    hasPhisInLocals = isPhiAtBlock(value);
+                    // also ignore illegal HiWords
+                    if (value != null && !value.isIllegal()) {
+                        i += value.kind.sizeInSlots();
+                    } else {
+                        i++;
+                    }
+                }
+                state = state.callerState();
+            } while (state != null);
+        }
+
+        // print values in locals
+        if (hasPhisInLocals) {
+            out.println();
+            out.println("Locals:");
+
+            FrameState state = stateBefore();
+            do {
+                int i = 0;
+                while (i < state.localsSize()) {
+                    Value value = state.localAt(i);
+                    if (value != null) {
+                        out.println(stateString(i, value));
+                        // also ignore illegal HiWords
+                        i += value.isIllegal() ? 1 : value.kind.sizeInSlots();
+                    } else {
+                        i++;
+                    }
+                }
+                out.println();
+                state = state.callerState();
+            } while (state != null);
+        }
+
+        // print values on stack
+        if (hasPhisOnStack) {
+            out.println();
+            out.println("Stack:");
+            int i = 0;
+            while (i < stateBefore().stackSize()) {
+                Value value = stateBefore().stackAt(i);
+                if (value != null) {
+                    out.println(stateString(i, value));
+                    i += value.kind.sizeInSlots();
+                } else {
+                    i++;
+                }
+            }
+        }
+
+    }
+
+
+
+    /**
+     * Determines if a given instruction is a phi whose {@linkplain Phi#block() 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).block() == 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#inputCount() 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#block() 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.block() == this) {
+                sb.append(" [");
+                for (int j = 0; j < phi.inputCount(); j++) {
+                    sb.append(' ');
+                    Value operand = phi.inputAt(j);
+                    if (operand != null) {
+                        sb.append(Util.valueString(operand));
+                    } else {
+                        sb.append("NULL");
+                    }
+                }
+                sb.append("] ");
+            }
+        }
+        if (value != null && value.hasSubst()) {
+            sb.append("alias ").append(Util.valueString(value.subst()));
+        }
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/BlockClosure.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.ir;
+
+/**
+ * The {@code BlockClosure} interface represents a closure for iterating over blocks.
+ *
+ * @author Ben L. Titzer
+ */
+public interface BlockClosure {
+    void apply(BlockBegin block);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/BlockEnd.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,152 @@
+/*
+ * 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.sun.c1x.ir;
+
+import java.util.*;
+
+import com.sun.c1x.util.*;
+import com.sun.c1x.value.*;
+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.
+ *
+ * @author Ben L. Titzer
+ */
+public abstract class BlockEnd extends Instruction {
+
+    BlockBegin begin;
+    final List<BlockBegin> successors;
+    FrameState stateAfter;
+
+    /**
+     * Constructs a new block end with the specified value type.
+     * @param kind the type of the value produced by this instruction
+     * @param stateAfter the frame state at the end of this block
+     * @param isSafepoint {@code true} if this instruction is a safepoint instruction
+     * @param successors the list of successor blocks. If {@code null}, a new one will be created.
+     */
+    public BlockEnd(CiKind kind, FrameState stateAfter, boolean isSafepoint, List<BlockBegin> successors) {
+        super(kind);
+        this.successors = successors == null ? new ArrayList<BlockBegin>(2) : successors;
+        setStateAfter(stateAfter);
+        if (isSafepoint) {
+            setFlag(Value.Flag.IsSafepoint);
+        }
+    }
+
+    public BlockEnd(CiKind kind, FrameState stateAfter, boolean isSafepoint) {
+        this(kind, stateAfter, isSafepoint, null);
+    }
+
+    /**
+     * Gets the state after the end of this block.
+     */
+    @Override
+    public FrameState stateAfter() {
+        return stateAfter;
+    }
+
+    public void setStateAfter(FrameState state) {
+        stateAfter = state;
+    }
+
+    /**
+     * Checks whether this instruction is a safepoint.
+     * @return {@code true} if this instruction is a safepoint
+     */
+    public boolean isSafepoint() {
+        return checkFlag(Value.Flag.IsSafepoint);
+    }
+
+    /**
+     * Gets the block begin associated with this block end.
+     * @return the beginning of this basic block
+     */
+    public BlockBegin begin() {
+        return begin;
+    }
+
+    /**
+     * Sets the basic block beginning for this block end. This should only
+     * be called from {@link BlockBegin}.
+     *
+     * @param block the beginning of this basic block
+     */
+    void setBegin(BlockBegin block) {
+        begin = block;
+    }
+
+    /**
+     * Substitutes a successor block in this block end's successor list. Note that
+     * this method updates all occurrences in the list.
+     * @param oldSucc the old successor to replace
+     * @param newSucc the new successor
+     */
+    public void substituteSuccessor(BlockBegin oldSucc, BlockBegin newSucc) {
+        assert newSucc != null;
+        Util.replaceAllInList(oldSucc, newSucc, successors);
+    }
+
+    /**
+     * Gets the successor corresponding to the default (fall through) case.
+     * @return the default successor
+     */
+    public BlockBegin defaultSuccessor() {
+        return successors.get(successors.size() - 1);
+    }
+
+    /**
+     * Searches for the specified successor and returns its index into the
+     * successor list if found.
+     * @param b the block to search for in the successor list
+     * @return the index of the block in the list if found; <code>-1</code> otherwise
+     */
+    public int successorIndex(BlockBegin b) {
+        final int max = successors.size();
+        for (int i = 0; i < max; i++) {
+            if (successors.get(i) == b) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Gets this block end's list of successors.
+     * @return the successor list
+     */
+    public List<BlockBegin> successors() {
+        return successors;
+    }
+
+    /**
+     * Gets the successor at a specified index.
+     * @param index the index of the successor
+     * @return the successor
+     */
+    public BlockBegin suxAt(int index) {
+        return successors.get(index);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/BlockList.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,150 @@
+/*
+ * 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.sun.c1x.ir;
+
+import java.util.*;
+
+/**
+ * The {@code BlockList} class implements a specialized list data structure for representing
+ * the predecessor and successor lists of basic blocks.
+ *
+ * @author Ben L. Titzer
+ */
+public class BlockList implements Iterable<BlockBegin> {
+
+    private BlockBegin[] array;
+    private int cursor;
+
+    BlockList(int sizeHint) {
+        if (sizeHint > 0) {
+            array = new BlockBegin[sizeHint];
+        } else {
+            array = new BlockBegin[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(BlockBegin 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();
+        }
+        BlockBegin t = array[index2];
+        array[index2] = array[index1];
+        array[index1] = t;
+    }
+
+    public void insert(int index, BlockBegin 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(BlockBegin block) {
+        growOne();
+        array[cursor++] = block;
+    }
+
+    public BlockBegin get(int index) {
+        if (index < 0 || index >= cursor) {
+            throw new IndexOutOfBoundsException();
+        }
+        return array[index];
+    }
+
+    public void replace(BlockBegin oldBlock, BlockBegin newBlock) {
+        for (int i = 0; i < cursor; i++) {
+            if (array[i] == oldBlock) {
+                array[i] = newBlock;
+            }
+        }
+    }
+
+    public boolean checkForSameBlock() {
+        if (cursor == 0) {
+            return true;
+        }
+        BlockBegin b = array[0];
+        for (int i = 1; i < cursor; i++) {
+            if (array[i] != b) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public Iterator<BlockBegin> iterator() {
+        return new Iter();
+    }
+
+    private void growOne() {
+        if (cursor == array.length) {
+            array = Arrays.copyOf(array, array.length * 3);
+        }
+    }
+
+    private class Iter implements Iterator<BlockBegin> {
+        private int pos;
+
+        public boolean hasNext() {
+            return pos < cursor;
+        }
+
+        public BlockBegin next() {
+            return array[pos++];
+        }
+
+        public void remove() {
+            BlockList.this.remove(pos);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/BoundsCheck.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,71 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+
+/**
+ * Performs a bounds check on the index variable given a length. Deoptimizes on index < 0 || index >= length.
+ *
+ * @author Thomas Wuerthinger
+ *
+ */
+public final class BoundsCheck extends Guard {
+
+    Value index;
+    Value length;
+
+    public BoundsCheck(Value index, Value length, FrameState stateBefore, Condition condition) {
+        super(condition, stateBefore);
+        this.index = index;
+        this.length = length;
+        assert index.kind == CiKind.Int;
+        assert length.kind == CiKind.Int;
+    }
+
+    public Value index() {
+        return index;
+    }
+
+    public Value length() {
+        return length;
+    }
+
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        index = closure.apply(index);
+        length = closure.apply(length);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitBoundsCheck(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("boundsCheck ").print(index).print(" ").print(length);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/BreakpointTrap.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,52 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.cri.ci.*;
+
+/**
+ * Instruction the emits a machine code instruction causing a breakpoint trap.
+ *
+ * @author Doug Simon
+ */
+public final class BreakpointTrap extends Instruction {
+
+    /**
+     * Creates a {@link BreakpointTrap} instance.
+     */
+    public BreakpointTrap() {
+        super(CiKind.Void);
+        setFlag(Flag.LiveSideEffect);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitBreakpointTrap(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("breakpoint_trap");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/CheckCast.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,96 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.util.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code CheckCast} instruction represents a {@link Bytecodes#CHECKCAST}.
+ *
+ * @author Ben L. Titzer
+ */
+public final class CheckCast extends TypeCheck {
+
+    /**
+     * Creates a new CheckCast instruction.
+     * @param targetClass the class being cast to
+     * @param object the instruction producing the object
+     * @param stateBefore the state before the cast
+     */
+    public CheckCast(RiType targetClass, Value targetClassInstruction, Value object, FrameState stateBefore) {
+        super(targetClass, targetClassInstruction, object, CiKind.Object, stateBefore);
+        initFlag(Flag.NonNull, object.isNonNull());
+    }
+
+    /**
+     * 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(Instruction i) {
+        if (i instanceof CheckCast) {
+            CheckCast o = (CheckCast) i;
+            return targetClass == o.targetClass && object == o.object;
+        }
+        return false;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("checkcast(").
+        print(object()).
+        print(",").
+        print(targetClassInstruction()).
+        print(") ").
+        print(CiUtil.toJavaName(targetClass()));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/CompareAndSwap.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,92 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.bytecode.*;
+
+/**
+ * Atomic update of a value in memory. Implements the {@link Bytecodes#PCMPSWP} family of instructions.
+ *
+ * Compares a suspected value with the actual value in a memory location.
+ * Iff they are same, a new value is placed into the location and the expected value is returned.
+ * Otherwise, the actual value is returned.
+ *
+ * @author Doug Simon
+ */
+public final class CompareAndSwap extends PointerOp {
+
+    /**
+     * The value to store.
+     */
+    Value expectedValue;
+
+    Value newValue;
+
+    /**
+     * Creates an instruction for a pointer store. If {@code displacement != null}, the effective of the address of the store is
+     * computed as the pointer plus a byte displacement plus a scaled index. Otherwise, the effective address is computed as the
+     * pointer plus a byte offset.
+     * @param pointer the value producing the pointer
+     * @param offset the value producing the byte offset
+     * @param expectedValue the value that must currently being in memory location for the swap to occur
+     * @param newValue the new value to store if the precondition is satisfied
+     * @param stateBefore the state before
+     * @param isVolatile {@code true} if the access is volatile
+     */
+    public CompareAndSwap(int opcode, Value pointer, Value offset, Value expectedValue, Value newValue, FrameState stateBefore, boolean isVolatile) {
+        super(expectedValue.kind, expectedValue.kind, opcode, pointer, null, offset, stateBefore, isVolatile);
+        assert offset != null;
+        this.expectedValue = expectedValue;
+        this.newValue = newValue;
+        setFlag(Flag.LiveStore);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitCompareAndSwap(this);
+    }
+
+    public Value expectedValue() {
+        return expectedValue;
+    }
+
+    public Value newValue() {
+        return newValue;
+    }
+
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        super.inputValuesDo(closure);
+        expectedValue = closure.apply(expectedValue);
+        newValue = closure.apply(newValue);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(Bytecodes.nameOf(opcode)).print("(").print(pointer());
+        out.print(" + ").print(offset());
+        out.print(", ").print(expectedValue()).print(", ").print(newValue()).print(')');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/CompareOp.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code CompareOp} instruction represents comparisons such as equals, not equal, etc.
+ *
+ * @author Ben L. Titzer
+ */
+public final class CompareOp extends Op2 {
+
+    /**
+     * 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 CompareOp(int opcode, CiKind kind, Value x, Value y) {
+        super(kind, opcode, x, y);
+        if (kind.isVoid()) {
+            // A compare that does not produce a value exists soley for it's side effect (i.e. setting condition codes)
+            setFlag(Flag.LiveSideEffect);
+        }
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitCompareOp(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(x()).
+            print(' ').
+            print(Bytecodes.operator(opcode)).
+            print(' ').
+            print(y());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/ComputeLinearScanOrder.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,752 @@
+/*
+ * 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.sun.c1x.ir;
+
+import java.util.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.debug.*;
+import com.sun.c1x.util.*;
+import com.sun.cri.ci.*;
+
+/**
+ * @author Thomas Wuerthinger
+ *
+ */
+public final class ComputeLinearScanOrder {
+
+    private final int maxBlockId; // the highest blockId of a block
+    private int numBlocks; // total number of blocks (smaller than maxBlockId)
+    private int numLoops; // total number of loops
+    private boolean iterativeDominators; // method requires iterative computation of dominators
+
+    List<BlockBegin> linearScanOrder; // the resulting list of blocks in correct order
+
+    final CiBitMap visitedBlocks; // used for recursive processing of blocks
+    final CiBitMap activeBlocks; // used for recursive processing of blocks
+    final CiBitMap dominatorBlocks; // temporary BitMap used for computation of dominator
+    final int[] forwardBranches; // number of incoming forward branches for each block
+    final List<BlockBegin> loopEndBlocks; // list of all loop end blocks collected during countEdges
+    BitMap2D loopMap; // two-dimensional bit set: a bit is set if a block is contained in a loop
+    final List<BlockBegin> workList; // temporary list (used in markLoops and computeOrder)
+
+    // accessors for visitedBlocks and activeBlocks
+    void initVisited() {
+        activeBlocks.clearAll();
+        visitedBlocks.clearAll();
+    }
+
+    boolean isVisited(BlockBegin b) {
+        return visitedBlocks.get(b.blockID);
+    }
+
+    boolean isActive(BlockBegin b) {
+        return activeBlocks.get(b.blockID);
+    }
+
+    void setVisited(BlockBegin b) {
+        assert !isVisited(b) : "already set";
+        visitedBlocks.set(b.blockID);
+    }
+
+    void setActive(BlockBegin b) {
+        assert !isActive(b) : "already set";
+        activeBlocks.set(b.blockID);
+    }
+
+    void clearActive(BlockBegin b) {
+        assert isActive(b) : "not already";
+        activeBlocks.clear(b.blockID);
+    }
+
+    // accessors for forwardBranches
+    void incForwardBranches(BlockBegin b) {
+        forwardBranches[b.blockID]++;
+    }
+
+    int decForwardBranches(BlockBegin b) {
+        return --forwardBranches[b.blockID];
+    }
+
+    // accessors for loopMap
+    boolean isBlockInLoop(int loopIdx, BlockBegin b) {
+        return loopMap.at(loopIdx, b.blockID);
+    }
+
+    void setBlockInLoop(int loopIdx, BlockBegin b) {
+        loopMap.setBit(loopIdx, b.blockID);
+    }
+
+    void clearBlockInLoop(int loopIdx, int blockId) {
+        loopMap.clearBit(loopIdx, blockId);
+    }
+
+    // accessors for final result
+    public List<BlockBegin> linearScanOrder() {
+        return linearScanOrder;
+    }
+
+    public int numLoops() {
+        return numLoops;
+    }
+
+    public ComputeLinearScanOrder(int maxBlockId, BlockBegin startBlock) {
+
+        this.maxBlockId = maxBlockId;
+        visitedBlocks = new CiBitMap(maxBlockId);
+        activeBlocks = new CiBitMap(maxBlockId);
+        dominatorBlocks = new CiBitMap(maxBlockId);
+        forwardBranches = new int[maxBlockId];
+        loopEndBlocks = new ArrayList<BlockBegin>(8);
+        workList = new ArrayList<BlockBegin>(8);
+
+        splitCriticalEdges();
+
+        countEdges(startBlock, null);
+
+        if (numLoops > 0) {
+            markLoops();
+            clearNonNaturalLoops(startBlock);
+            assignLoopDepth(startBlock);
+        }
+
+        computeOrder(startBlock);
+        computeDominators();
+
+        printBlocks();
+        assert verify();
+    }
+
+    void splitCriticalEdges() {
+        // TODO: move critical edge splitting from IR to here
+    }
+
+    /**
+     * 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(BlockBegin cur, BlockBegin parent) {
+        if (C1XOptions.TraceLinearScanLevel >= 3) {
+            TTY.println("Counting edges for block B%d%s", cur.blockID, parent == null ? "" : " coming from B" + parent.blockID);
+        }
+        assert cur.dominator() == null : "dominator already initialized";
+
+        if (isActive(cur)) {
+            if (C1XOptions.TraceLinearScanLevel >= 3) {
+                TTY.println("backward branch");
+            }
+            assert isVisited(cur) : "block must be visited when block is active";
+            assert parent != null : "must have parent";
+
+            cur.setBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader);
+            cur.setBlockFlag(BlockBegin.BlockFlag.BackwardBranchTarget);
+
+            parent.setBlockFlag(BlockBegin.BlockFlag.LinearScanLoopEnd);
+
+            // When a loop header is also the start of an exception handler, then the backward branch is
+            // an exception edge. Because such edges are usually critical edges which cannot be split, the
+            // loop must be excluded here from processing.
+            if (cur.checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry)) {
+                // Make sure that dominators are correct in this weird situation
+                iterativeDominators = true;
+                return;
+            }
+//            assert parent.numberOfSux() == 1 && parent.suxAt(0) == cur : "loop end blocks must have one successor (critical edges are split)";
+
+            loopEndBlocks.add(parent);
+            return;
+        }
+
+        // increment number of incoming forward branches
+        incForwardBranches(cur);
+
+        if (isVisited(cur)) {
+            if (C1XOptions.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);
+        }
+        for (i = cur.numberOfExceptionHandlers() - 1; i >= 0; i--) {
+            countEdges(cur.exceptionHandlerAt(i), cur);
+        }
+
+        clearActive(cur);
+
+        // Each loop has a unique number.
+        // When multiple loops are nested, assignLoopDepth assumes that the
+        // innermost loop has the lowest number. This is guaranteed by setting
+        // the loop number after the recursive calls for the successors above
+        // have returned.
+        if (cur.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader)) {
+            assert cur.loopIndex() == -1 : "cannot set loop-index twice";
+            if (C1XOptions.TraceLinearScanLevel >= 3) {
+                TTY.println("Block B%d is loop header of loop %d", cur.blockID, numLoops);
+            }
+
+            cur.setLoopIndex(numLoops);
+            numLoops++;
+        }
+
+        if (C1XOptions.TraceLinearScanLevel >= 3) {
+            TTY.println("Finished counting edges for block B%d", cur.blockID);
+        }
+    }
+
+    void markLoops() {
+        if (C1XOptions.TraceLinearScanLevel >= 3) {
+            TTY.println("----- marking loops");
+        }
+
+        loopMap = new BitMap2D(numLoops, maxBlockId);
+
+        for (int i = loopEndBlocks.size() - 1; i >= 0; i--) {
+            BlockBegin loopEnd = loopEndBlocks.get(i);
+            BlockBegin loopStart = loopEnd.suxAt(0);
+            int loopIdx = loopStart.loopIndex();
+
+            if (C1XOptions.TraceLinearScanLevel >= 3) {
+                TTY.println("Processing loop from B%d to B%d (loop %d):", loopStart.blockID, loopEnd.blockID, loopIdx);
+            }
+            assert loopEnd.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopEnd) : "loop end flag must be set";
+//            assert loopEnd.numberOfSux() == 1 : "incorrect number of successors";
+            assert loopStart.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader) : "loop header flag must be set";
+            assert loopIdx >= 0 && loopIdx < numLoops : "loop index not set";
+            assert workList.isEmpty() : "work list must be empty before processing";
+
+            // add the end-block of the loop to the working list
+            workList.add(loopEnd);
+            setBlockInLoop(loopIdx, loopEnd);
+            do {
+                BlockBegin cur = workList.remove(workList.size() - 1);
+
+                if (C1XOptions.TraceLinearScanLevel >= 3) {
+                    TTY.println("    processing B%d", cur.blockID);
+                }
+                assert isBlockInLoop(loopIdx, cur) : "bit in loop map must be set when block is in work list";
+
+                // recursive processing of all predecessors ends when start block of loop is reached
+                if (cur != loopStart && !cur.checkBlockFlag(BlockBegin.BlockFlag.OsrEntry)) {
+                    for (int j = cur.numberOfPreds() - 1; j >= 0; j--) {
+                        BlockBegin pred = cur.predAt(j);
+
+                        if (!isBlockInLoop(loopIdx, pred)) {
+                            // this predecessor has not been processed yet, so add it to work list
+                            if (C1XOptions.TraceLinearScanLevel >= 3) {
+                                TTY.println("    pushing B%d", pred.blockID);
+                            }
+                            workList.add(pred);
+                            setBlockInLoop(loopIdx, pred);
+                        }
+                    }
+                }
+            } while (!workList.isEmpty());
+        }
+    }
+
+    // check for non-natural loops (loops where the loop header does not dominate
+    // all other loop blocks = loops with multiple entries).
+    // such loops are ignored
+    void clearNonNaturalLoops(BlockBegin startBlock) {
+        for (int i = numLoops - 1; i >= 0; i--) {
+            if (isBlockInLoop(i, startBlock)) {
+                // loop i contains the entry block of the method.
+                // this is not a natural loop, so ignore it
+                if (C1XOptions.TraceLinearScanLevel >= 2) {
+                    TTY.println("Loop %d is non-natural, so it is ignored", i);
+                }
+
+                for (int blockId = maxBlockId - 1; blockId >= 0; blockId--) {
+                    clearBlockInLoop(i, blockId);
+                }
+                iterativeDominators = true;
+            }
+        }
+    }
+
+    void assignLoopDepth(BlockBegin startBlock) {
+        if (C1XOptions.TraceLinearScanLevel >= 3) {
+            TTY.println("----- computing loop-depth and weight");
+        }
+        initVisited();
+
+        assert workList.isEmpty() : "work list must be empty before processing";
+        workList.add(startBlock);
+
+        do {
+            BlockBegin cur = workList.remove(workList.size() - 1);
+
+            if (!isVisited(cur)) {
+                setVisited(cur);
+                if (C1XOptions.TraceLinearScanLevel >= 4) {
+                    TTY.println("Computing loop depth for block B%d", cur.blockID);
+                }
+
+                // compute loop-depth and loop-index for the block
+                assert cur.loopDepth() == 0 : "cannot set loop-depth twice";
+                int i;
+                int loopDepth = 0;
+                int minLoopIdx = -1;
+                for (i = numLoops - 1; i >= 0; i--) {
+                    if (isBlockInLoop(i, cur)) {
+                        loopDepth++;
+                        minLoopIdx = i;
+                    }
+                }
+                cur.setLoopDepth(loopDepth);
+                cur.setLoopIndex(minLoopIdx);
+
+                // append all unvisited successors to work list
+                for (i = cur.numberOfSux() - 1; i >= 0; i--) {
+                    workList.add(cur.suxAt(i));
+                }
+                for (i = cur.numberOfExceptionHandlers() - 1; i >= 0; i--) {
+                    workList.add(cur.exceptionHandlerAt(i));
+                }
+            }
+        } while (!workList.isEmpty());
+    }
+
+    BlockBegin commonDominator(BlockBegin a, BlockBegin b) {
+        assert a != null && b != null : "must have input blocks";
+
+        dominatorBlocks.clearAll();
+        while (a != null) {
+            dominatorBlocks.set(a.blockID);
+            assert a.dominator() != null || a == linearScanOrder.get(0) : "dominator must be initialized";
+            a = a.dominator();
+        }
+        while (b != null && !dominatorBlocks.get(b.blockID)) {
+            assert b.dominator() != null || b == linearScanOrder.get(0) : "dominator must be initialized";
+            b = b.dominator();
+        }
+
+        assert b != null : "could not find dominator";
+        return b;
+    }
+
+    void computeDominator(BlockBegin cur, BlockBegin parent) {
+        if (cur.dominator() == null) {
+            if (C1XOptions.TraceLinearScanLevel >= 4) {
+                TTY.println("DOM: initializing dominator of B%d to B%d", cur.blockID, parent.blockID);
+            }
+            if (cur.isExceptionEntry()) {
+                assert parent.dominator() != null;
+                cur.setDominator(parent.dominator());
+            } else {
+                cur.setDominator(parent);
+            }
+
+        } else if (!(cur.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader) && parent.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopEnd))) {
+            if (C1XOptions.TraceLinearScanLevel >= 4) {
+                TTY.println("DOM: computing dominator of B%d: common dominator of B%d and B%d is B%d", cur.blockID, parent.blockID, cur.dominator().blockID, commonDominator(cur.dominator(), parent).blockID);
+            }
+            assert cur.numberOfPreds() > 1 : "";
+            cur.setDominator(commonDominator(cur.dominator(), parent));
+        }
+    }
+
+    int computeWeight(BlockBegin cur) {
+        BlockBegin singleSux = null;
+        if (cur.numberOfSux() == 1) {
+            singleSux = cur.suxAt(0);
+        }
+
+        // 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.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader)) {
+            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.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopEnd)) {
+            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.checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry)) {
+            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;
+    }
+
+    boolean readyForProcessing(BlockBegin 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;
+    }
+
+    void sortIntoWorkList(BlockBegin 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 (C1XOptions.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 (C1XOptions.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";
+        }
+    }
+
+    void appendBlock(BlockBegin cur) {
+        if (C1XOptions.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);
+    }
+
+    void computeOrder(BlockBegin startBlock) {
+        if (C1XOptions.TraceLinearScanLevel >= 3) {
+            TTY.println("----- computing final block order");
+        }
+
+        // the start block is always the first block in the linear scan order
+        linearScanOrder = new ArrayList<BlockBegin>(numBlocks);
+        appendBlock(startBlock);
+
+        assert startBlock.end() instanceof Base : "start block must end with Base-instruction";
+        BlockBegin stdEntry = ((Base) startBlock.end()).standardEntry();
+        BlockBegin osrEntry = ((Base) startBlock.end()).osrEntry();
+
+        BlockBegin suxOfOsrEntry = null;
+        if (osrEntry != null) {
+            // special handling for osr entry:
+            // ignore the edge between the osr entry and its successor for processing
+            // the osr entry block is added manually below
+            assert osrEntry.numberOfSux() == 1 : "osr entry must have exactly one successor";
+            assert osrEntry.suxAt(0).numberOfPreds() >= 2 : "sucessor of osr entry must have two predecessors (otherwise it is not present in normal control flow)";
+
+            suxOfOsrEntry = osrEntry.suxAt(0);
+            decForwardBranches(suxOfOsrEntry);
+
+            computeDominator(osrEntry, startBlock);
+            iterativeDominators = true;
+        }
+        computeDominator(stdEntry, startBlock);
+
+        // start processing with standard entry block
+        assert workList.isEmpty() : "list must be empty before processing";
+
+        if (readyForProcessing(stdEntry)) {
+            sortIntoWorkList(stdEntry);
+        } else {
+            throw new CiBailout("the stdEntry must be ready for processing (otherwise, the method has no start block)");
+        }
+
+        do {
+            BlockBegin cur = workList.remove(workList.size() - 1);
+
+            if (cur == suxOfOsrEntry) {
+                // the osr entry block is ignored in normal processing : it is never added to the
+                // work list. Instead : it is added as late as possible manually here.
+                appendBlock(osrEntry);
+                computeDominator(cur, osrEntry);
+            }
+            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++) {
+                BlockBegin sux = cur.suxAt(i);
+                computeDominator(sux, cur);
+                if (readyForProcessing(sux)) {
+                    sortIntoWorkList(sux);
+                }
+            }
+            numSux = cur.numberOfExceptionHandlers();
+            for (i = 0; i < numSux; i++) {
+                BlockBegin sux = cur.exceptionHandlerAt(i);
+                computeDominator(sux, cur);
+                if (readyForProcessing(sux)) {
+                    sortIntoWorkList(sux);
+                }
+            }
+        } while (workList.size() > 0);
+    }
+
+    boolean computeDominatorsIter() {
+        boolean changed = false;
+        int numBlocks = linearScanOrder.size();
+
+        assert linearScanOrder.get(0).dominator() == null : "must not have dominator";
+        assert linearScanOrder.get(0).numberOfPreds() == 0 : "must not have predecessors";
+        for (int i = 1; i < numBlocks; i++) {
+            BlockBegin block = linearScanOrder.get(i);
+
+            assert block.numberOfPreds() > 0;
+            BlockBegin dominator = block.predAt(0);
+            if (block.isExceptionEntry()) {
+                dominator = dominator.dominator();
+            }
+
+            int numPreds = block.numberOfPreds();
+            for (int j = 1; j < numPreds; j++) {
+                BlockBegin curPred = block.predAt(j);
+                if (block.isExceptionEntry()) {
+                    curPred = curPred.dominator();
+                }
+                dominator = commonDominator(dominator, curPred);
+            }
+
+            if (dominator != block.dominator()) {
+                if (C1XOptions.TraceLinearScanLevel >= 4) {
+                    TTY.println("DOM: updating dominator of B%d from B%d to B%d", block.blockID, block.dominator().blockID, dominator.blockID);
+                }
+                block.setDominator(dominator);
+                changed = true;
+            }
+        }
+        return changed;
+    }
+
+    void computeDominators() {
+        if (C1XOptions.TraceLinearScanLevel >= 3) {
+            TTY.println("----- computing dominators (iterative computation reqired: %b)", iterativeDominators);
+        }
+
+        // iterative computation of dominators is only required for methods with non-natural loops
+        // and OSR-methods. For all other methods : the dominators computed when generating the
+        // linear scan block order are correct.
+        if (iterativeDominators) {
+            do {
+                if (C1XOptions.TraceLinearScanLevel >= 1) {
+                    TTY.println("DOM: next iteration of fix-point calculation");
+                }
+            } while (computeDominatorsIter());
+        }
+
+        // check that dominators are correct
+        assert !computeDominatorsIter() : "fix point not reached";
+    }
+
+    public void printBlocks() {
+        if (C1XOptions.TraceLinearScanLevel >= 2) {
+            TTY.println("----- loop information:");
+            for (BlockBegin cur : linearScanOrder) {
+                TTY.print(String.format("%4d: B%02d: ", cur.linearScanNumber(), cur.blockID));
+                for (int loopIdx = 0; loopIdx < numLoops; loopIdx++) {
+                    TTY.print(String.format("%d = %b ", loopIdx, isBlockInLoop(loopIdx, cur)));
+                }
+                TTY.println(String.format(" . loopIndex: %2d, loopDepth: %2d", cur.loopIndex(), cur.loopDepth()));
+            }
+        }
+
+        if (C1XOptions.TraceLinearScanLevel >= 1) {
+            TTY.println("----- linear-scan block order:");
+            for (BlockBegin cur : linearScanOrder) {
+                TTY.print(String.format("%4d: B%02d    loop: %2d  depth: %2d", cur.linearScanNumber(), cur.blockID, cur.loopIndex(), cur.loopDepth()));
+
+                TTY.print(cur.isExceptionEntry() ? " ex" : "   ");
+                TTY.print(cur.isCriticalEdgeSplit() ? " ce" : "   ");
+                TTY.print(cur.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader) ? " lh" : "   ");
+                TTY.print(cur.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopEnd) ? " le" : "   ");
+
+                if (cur.dominator() != null) {
+                    TTY.print("    dom: B%d ", cur.dominator().blockID);
+                } else {
+                    TTY.print("    dom: null ");
+                }
+
+                if (cur.numberOfPreds() > 0) {
+                    TTY.print("    preds: ");
+                    for (int j = 0; j < cur.numberOfPreds(); j++) {
+                        BlockBegin 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++) {
+                        BlockBegin sux = cur.suxAt(j);
+                        TTY.print("B%d ", sux.blockID);
+                    }
+                }
+                if (cur.numberOfExceptionHandlers() > 0) {
+                    TTY.print("    ex: ");
+                    for (int j = 0; j < cur.numberOfExceptionHandlers(); j++) {
+                        BlockBegin ex = cur.exceptionHandlerAt(j);
+                        TTY.print("B%d ", ex.blockID);
+                    }
+                }
+                TTY.println();
+            }
+        }
+    }
+
+    boolean verify() {
+        assert linearScanOrder.size() == numBlocks : "wrong number of blocks in list";
+
+        if (C1XOptions.StressLinearScan) {
+            // blocks are scrambled when StressLinearScan is used
+            return true;
+        }
+
+        // check that all successors of a block have a higher linear-scan-number
+        // and that all predecessors of a block have a lower linear-scan-number
+        // (only backward branches of loops are ignored)
+        int i;
+        for (i = 0; i < linearScanOrder.size(); i++) {
+            BlockBegin cur = linearScanOrder.get(i);
+
+            assert cur.linearScanNumber() == i : "incorrect linearScanNumber";
+            assert cur.linearScanNumber() >= 0 && cur.linearScanNumber() == linearScanOrder.indexOf(cur) : "incorrect linearScanNumber";
+
+            for (BlockBegin sux : cur.end().successors()) {
+                assert sux.linearScanNumber() >= 0 && sux.linearScanNumber() == linearScanOrder.indexOf(sux) : "incorrect linearScanNumber";
+                if (!cur.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopEnd)) {
+                    assert cur.linearScanNumber() < sux.linearScanNumber() : "invalid order";
+                }
+                if (cur.loopDepth() == sux.loopDepth()) {
+                    assert cur.loopIndex() == sux.loopIndex() || sux.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader) : "successing blocks with same loop depth must have same loop index";
+                }
+            }
+
+            for (BlockBegin pred : cur.predecessors()) {
+                assert pred.linearScanNumber() >= 0 && pred.linearScanNumber() == linearScanOrder.indexOf(pred) : "incorrect linearScanNumber";
+                if (!cur.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader)) {
+                    assert cur.linearScanNumber() > pred.linearScanNumber() : "invalid order";
+                }
+                if (cur.loopDepth() == pred.loopDepth()) {
+                    assert cur.loopIndex() == pred.loopIndex() || cur.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader) : "successing blocks with same loop depth must have same loop index";
+                }
+
+                assert cur.dominator().linearScanNumber() <= pred.linearScanNumber() : "dominator must be before predecessors";
+            }
+
+            // check dominator
+            if (i == 0) {
+                assert cur.dominator() == null : "first block has no dominator";
+            } else {
+                assert cur.dominator() != null : "all but first block must have dominator";
+            }
+            assert cur.numberOfPreds() != 1 || cur.dominator() == cur.predAt(0) || cur.isExceptionEntry() : "Single predecessor must also be dominator";
+        }
+
+        // check that all loops are continuous
+        for (int loopIdx = 0; loopIdx < numLoops; loopIdx++) {
+            int blockIdx = 0;
+            assert !isBlockInLoop(loopIdx, linearScanOrder.get(blockIdx)) : "the first block must not be present in any loop";
+
+            // skip blocks before the loop
+            while (blockIdx < numBlocks && !isBlockInLoop(loopIdx, linearScanOrder.get(blockIdx))) {
+                blockIdx++;
+            }
+            // skip blocks of loop
+            while (blockIdx < numBlocks && isBlockInLoop(loopIdx, linearScanOrder.get(blockIdx))) {
+                blockIdx++;
+            }
+            // after the first non-loop block : there must not be another loop-block
+            while (blockIdx < numBlocks) {
+                assert !isBlockInLoop(loopIdx, linearScanOrder.get(blockIdx)) : "loop not continuous in linear-scan order";
+                blockIdx++;
+            }
+        }
+
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/Condition.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,206 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.cri.bytecode.Bytecodes.*;
+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("|<|"),
+
+    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();
+    }
+
+    /**
+     * 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 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 UnsignedComparisons.aboveOrEqual(x, y);
+                    case BE: return UnsignedComparisons.belowOrEqual(x, y);
+                    case AT: return UnsignedComparisons.aboveThan(x, y);
+                    case BT: return UnsignedComparisons.belowThan(x, 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;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/Constant.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,161 @@
+/*
+ * 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.sun.c1x.ir;
+
+import static com.sun.c1x.C1XCompilation.*;
+
+import com.sun.c1x.debug.*;
+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.
+ *
+ * @author Ben L. Titzer
+ */
+public final class Constant extends Instruction {
+
+    public final CiConstant value;
+
+    /**
+     * Constructs a new instruction representing the specified constant.
+     * @param value the constant
+     */
+    public Constant(CiConstant value) {
+        super(value.kind.stackKind());
+        this.value = value;
+        initFlag(Value.Flag.NonNull, value.isNonNull());
+    }
+
+    @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
+     * @return an instruction representing the double
+     */
+    public static Constant forDouble(double d) {
+        return new Constant(CiConstant.forDouble(d));
+    }
+
+    /**
+     * 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) {
+        return new Constant(CiConstant.forFloat(f));
+    }
+
+    /**
+     * 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) {
+        return new Constant(CiConstant.forLong(i));
+    }
+
+    /**
+     * 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) {
+        return new Constant(CiConstant.forInt(i));
+    }
+
+    /**
+     * 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) {
+        return new Constant(CiConstant.forBoolean(i));
+    }
+
+    /**
+     * 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) {
+        return new Constant(CiConstant.forJsr(i));
+    }
+
+    /**
+     * 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) {
+        return new Constant(CiConstant.forObject(o));
+    }
+
+    /**
+     * 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) {
+        return new Constant(CiConstant.forWord(val));
+    }
+
+    @Override
+    public String toString() {
+        return super.toString() + "(" + value + ")";
+    }
+
+    @Override
+    public int valueNumber() {
+        return 0x50000000 | value.hashCode();
+    }
+
+    @Override
+    public boolean valueEqual(Instruction i) {
+        return i instanceof Constant && ((Constant) i).value.equivalent(this.value);
+    }
+
+    @Override
+    public RiType declaredType() {
+        RiRuntime runtime = compilation().runtime;
+        if (kind.isPrimitive()) {
+            runtime.asRiType(kind);
+        }
+        return runtime.getTypeOf(asConstant());
+    }
+
+    @Override
+    public RiType exactType() {
+        return declaredType();
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(value.valueString());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/Convert.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.util.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code Convert} class represents a conversion between primitive types.
+ *
+ * @author Ben L. Titzer
+ */
+public final class Convert extends Instruction {
+
+    /**
+     * The opcode for this conversion operation.
+     */
+    public final int opcode;
+
+    Value value;
+
+    /**
+     * 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
+     */
+    public Convert(int opcode, Value value, CiKind kind) {
+        super(kind);
+        this.opcode = opcode;
+        this.value = value;
+    }
+
+    /**
+     * Gets the instruction which produces the input value to this instruction.
+     * @return the input value instruction
+     */
+    public Value value() {
+        return value;
+    }
+
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        value = closure.apply(value);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitConvert(this);
+    }
+
+    @Override
+    public int valueNumber() {
+        return Util.hash1(opcode, value);
+    }
+
+    @Override
+    public boolean valueEqual(Instruction 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(')');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/DefaultValueVisitor.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,109 @@
+/*
+ * 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.sun.c1x.ir;
+
+/**
+ * A default implementation of {@link ValueVisitor} that simply
+ * does nothing for each value visited. This convenience class
+ * simplifies implementing a value visitor that is only interested
+ * in a subset of the value types.
+ *
+ * @author Doug Simon
+ */
+public class DefaultValueVisitor extends ValueVisitor {
+
+    /**
+     * All the specific visitor methods in this class call this method by default.
+     *
+     * @param value the value being visited
+     */
+    protected  void visit(Value value) {
+    }
+
+    // Checkstyle: stop
+    @Override public void visitArithmeticOp(ArithmeticOp i) { visit(i); }
+    @Override public void visitArrayCopy(ArrayCopy i) { visit(i); }
+    @Override public void visitArrayLength(ArrayLength i) { visit(i); }
+    @Override public void visitBase(Base i) { visit(i); }
+    @Override public void visitBlockBegin(BlockBegin i) { visit(i); }
+    @Override public void visitBoundsCheck(BoundsCheck i) { visit(i); }
+    @Override public void visitBreakpointTrap(BreakpointTrap i) {visit(i); }
+    @Override public void visitCheckCast(CheckCast i) { visit(i); }
+    @Override public void visitCompareOp(CompareOp i) { visit(i); }
+    @Override public void visitCompareAndSwap(CompareAndSwap i) { visit(i); }
+    @Override public void visitConstant(Constant i) { visit(i); }
+    @Override public void visitConvert(Convert i) { visit(i); }
+    @Override public void visitExceptionObject(ExceptionObject i) { visit(i); }
+    @Override public void visitGoto(Goto i) { visit(i); }
+    @Override public void visitIncrementRegister(IncrementRegister i) { visit(i); }
+    @Override public void visitIf(If i) { visit(i); }
+    @Override public void visitIfOp(IfOp i) { visit(i); }
+    @Override public void visitInfopoint(Infopoint i) { visit(i); }
+    @Override public void visitInstanceOf(InstanceOf i) { visit(i); }
+    @Override public void visitIntrinsic(Intrinsic i) { visit(i); }
+    @Override public void visitInvoke(Invoke i) { visit(i); }
+    @Override public void visitLoadField(LoadField i) { visit(i); }
+    @Override public void visitLoadIndexed(LoadIndexed i) { visit(i); }
+    @Override public void visitLoadPointer(LoadPointer i) { visit(i); }
+    @Override public void visitLoadRegister(LoadRegister i) { visit(i); }
+    @Override public void visitAllocateStackHandle(StackHandle i) { visit(i); }
+    @Override public void visitLocal(Local i) { visit(i); }
+    @Override public void visitLogicOp(LogicOp i) { visit(i); }
+    @Override public void visitLookupSwitch(LookupSwitch i) { visit(i); }
+    @Override public void visitMemoryBarrier(MemoryBarrier i) { visit(i); }
+    @Override public void visitMonitorAddress(MonitorAddress i) { visit(i); }
+    @Override public void visitMonitorEnter(MonitorEnter i) { visit(i); }
+    @Override public void visitMonitorExit(MonitorExit i) { visit(i); }
+    @Override public void visitNativeCall(NativeCall i) { visit(i); }
+    @Override public void visitNegateOp(NegateOp i) { visit(i); }
+    @Override public void visitNewInstance(NewInstance i) { visit(i); }
+    @Override public void visitNewMultiArray(NewMultiArray i) { visit(i); }
+    @Override public void visitNewObjectArray(NewObjectArray i) { visit(i); }
+    @Override public void visitNewObjectArrayClone(NewObjectArrayClone i) { visit(i); }
+    @Override public void visitNewTypeArray(NewTypeArray i) { visit(i); }
+    @Override public void visitNullCheck(NullCheck i) { visit(i); }
+    @Override public void visitOsrEntry(OsrEntry i) { visit(i); }
+    @Override public void visitPause(Pause i) { visit(i); }
+    @Override public void visitPhi(Phi i) { visit(i); }
+    @Override public void visitResolveClass(ResolveClass i) { visit(i); }
+    @Override public void visitReturn(Return i) { visit(i); }
+    @Override public void visitShiftOp(ShiftOp i) { visit(i); }
+    @Override public void visitSignificantBit(SignificantBitOp i) { visit(i); }
+    @Override public void visitStackAllocate(StackAllocate i) { visit(i); }
+    @Override public void visitStoreField(StoreField i) { visit(i); }
+    @Override public void visitStoreIndexed(StoreIndexed i) { visit(i); }
+    @Override public void visitStorePointer(StorePointer i) { visit(i); }
+    @Override public void visitStoreRegister(StoreRegister i) { visit(i); }
+    @Override public void visitTableSwitch(TableSwitch i) { visit(i); }
+    @Override public void visitTemplateCall(TemplateCall i) { visit(i); }
+    @Override public void visitTypeEqualityCheck(TypeEqualityCheck i) { visit(i); }
+    @Override public void visitThrow(Throw i) { visit(i); }
+    @Override public void visitUnsafeCast(UnsafeCast i) { visit(i); }
+    @Override public void visitUnsafeGetObject(UnsafeGetObject i) { visit(i); }
+    @Override public void visitUnsafeGetRaw(UnsafeGetRaw i) { visit(i); }
+    @Override public void visitUnsafePrefetchRead(UnsafePrefetchRead i) { visit(i); }
+    @Override public void visitUnsafePrefetchWrite(UnsafePrefetchWrite i) { visit(i); }
+    @Override public void visitUnsafePutObject(UnsafePutObject i) { visit(i); }
+    @Override public void visitUnsafePutRaw(UnsafePutRaw i) { visit(i); }
+    @Override public void visitUnsignedCompareOp(UnsignedCompareOp i) { visit(i); }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/ExceptionHandler.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,201 @@
+/*
+ * 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.sun.c1x.ir;
+
+import java.util.*;
+
+import com.sun.c1x.lir.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code ExceptionHandler} class represents an exception handler for a Java bytecode method.
+ * There is exactly one instance of this class for every exception handler without any specific
+ * reference to an exception-throwing instruction covered by the handler. Then there is one
+ * instance per exception-throwing instruction that is used to record the frame state before
+ * execution of the instruction. The latter is used to generate exception adapter blocks
+ * (see section 3.4 of the paper <a href="http://www.usenix.org/events/vee05/full_papers/p132-wimmer.pdf">
+ * Optimized Interval Splitting in a Linear Scan Register Allocator</a>) where necessary.
+ *
+ * @author Ben L. Titzer
+ */
+public final class ExceptionHandler {
+
+    public static final List<ExceptionHandler> ZERO_HANDLERS = Collections.emptyList();
+
+    public final RiExceptionHandler handler;
+    private BlockBegin entryBlock;
+    private LIRList entryCode;
+    private int entryCodeOffset;
+    private int phiOperand;
+    private int scopeCount;
+    private int lirOpId;
+
+    public ExceptionHandler(RiExceptionHandler handler) {
+        this.handler = handler;
+        this.entryCodeOffset = -1;
+        this.phiOperand = -1;
+        this.scopeCount = -1;
+        this.lirOpId = -1;
+    }
+
+    public ExceptionHandler(ExceptionHandler other) {
+        this.handler = other.handler;
+        this.entryBlock = other.entryBlock;
+        this.entryCode = other.entryCode;
+        this.entryCodeOffset = other.entryCodeOffset;
+        this.phiOperand = other.phiOperand;
+        this.scopeCount = other.scopeCount;
+        this.lirOpId = other.lirOpId;
+    }
+
+    @Override
+    public String toString() {
+        return "XHandler(Block=" + entryBlock.blockID + ") " + handler;
+    }
+
+    /**
+     * Gets the compiler interface object that describes this exception handler,
+     * including the bytecode ranges.
+     * @return the compiler interface exception handler
+     */
+    public RiExceptionHandler handler() {
+        return handler;
+    }
+
+    /**
+     * Gets the bytecode index of the handler (catch block).
+     * @return the bytecode index of the handler
+     */
+    public int handlerBCI() {
+        return handler.handlerBCI();
+    }
+
+    /**
+     * Utility method to check if this exception handler covers the specified bytecode index.
+     * @param bci the bytecode index to check
+     * @return {@code true} if this exception handler covers the specified bytecode
+     */
+    public boolean covers(int bci) {
+        return handler.startBCI() <= bci && bci < handler.endBCI();
+    }
+
+    /**
+     * Gets the entry block for this exception handler.
+     * @return the entry block
+     */
+    public BlockBegin entryBlock() {
+        return entryBlock;
+    }
+
+    /**
+     * Gets the PC offset of the handler entrypoint, which is used by
+     * the runtime to forward exception points to their catch sites.
+     * @return the pc offset of the handler entrypoint
+     */
+    public int entryCodeOffset() {
+        return entryCodeOffset;
+    }
+
+    public int phiOperand() {
+        return phiOperand;
+    }
+
+    public int scopeCount() {
+        return scopeCount;
+    }
+
+    public void setEntryBlock(BlockBegin entry) {
+        entryBlock = entry;
+    }
+
+    public void setEntryCodeOffset(int pco) {
+        entryCodeOffset = pco;
+    }
+
+    public void setPhiOperand(int phi) {
+        phiOperand = phi;
+    }
+
+    public void setScopeCount(int count) {
+        scopeCount = count;
+    }
+
+    public boolean isCatchAll() {
+        return handler.catchTypeCPI() == 0;
+    }
+
+    public static boolean couldCatch(List<ExceptionHandler> exceptionHandlers, RiType klass, boolean typeIsExact) {
+        // the type is unknown so be conservative
+        if (!klass.isResolved()) {
+            return true;
+        }
+
+        for (int i = 0; i < exceptionHandlers.size(); i++) {
+            ExceptionHandler handler = exceptionHandlers.get(i);
+            if (handler.isCatchAll()) {
+                // catch of ANY
+                return true;
+            }
+            RiType handlerKlass = handler.handler.catchType();
+            // if it's unknown it might be catchable
+            if (!handlerKlass.isResolved()) {
+                return true;
+            }
+            // if the throw type is definitely a subtype of the catch type
+            // then it can be caught.
+            if (klass.isSubtypeOf(handlerKlass)) {
+                return true;
+            }
+            if (!typeIsExact) {
+                // If the type isn't exactly known then it can also be caught by
+                // catch statements where the inexact type is a subtype of the
+                // catch type.
+                // given: foo extends bar extends Exception
+                // throw bar can be caught by catch foo, catch bar, and catch
+                // Exception, however it can't be caught by any handlers without
+                // bar in its type hierarchy.
+                if (handlerKlass.isSubtypeOf(klass)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public int lirOpId() {
+        return lirOpId;
+    }
+
+    public LIRList entryCode() {
+        return entryCode;
+    }
+
+    public void setLirOpId(int throwingOpId) {
+        lirOpId = throwingOpId;
+    }
+
+    public void setEntryCode(LIRList entryCode) {
+        this.entryCode = entryCode;
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/ExceptionObject.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,66 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code ExceptionObject} instruction represents the incoming exception object to an exception handler.
+ *
+ * @author Ben L. Titzer
+ */
+public final class ExceptionObject extends Instruction {
+
+    /**
+     * Debug info is required if safepoints are placed at exception handlers.
+     */
+    public final FrameState stateBefore;
+
+    /**
+     * Constructs a new ExceptionObject instruction.
+     * @param stateBefore TODO
+     */
+    public ExceptionObject(FrameState stateBefore) {
+        super(CiKind.Object);
+        setFlag(Flag.NonNull);
+        setFlag(Flag.LiveSideEffect);
+        this.stateBefore = stateBefore;
+    }
+
+    @Override
+    public FrameState stateBefore() {
+        return stateBefore;
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitExceptionObject(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("incoming exception");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/Goto.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code Goto} instruction represents the end of a block with an unconditional jump to another block.
+ *
+ * @author Ben L. Titzer
+ */
+public final class Goto extends BlockEnd {
+
+    /**
+     * Constructs a new Goto instruction.
+     * @param succ the successor block of the goto
+     * @param stateAfter the frame state at the end of this block
+     * @param isSafepoint {@code true} if the goto should be considered a safepoint (e.g. backward branch)
+     */
+    public Goto(BlockBegin succ, FrameState stateAfter, boolean isSafepoint) {
+        super(CiKind.Illegal, stateAfter, isSafepoint);
+        successors.add(succ);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitGoto(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("goto B").print(defaultSuccessor().blockID);
+        if (isSafepoint()) {
+            out.print(" (safepoint)");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/Guard.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,43 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+
+/**
+ * Calls the deoptimization runtime method if the condition is met.
+ *
+ * @author Thomas Wuerthinger
+ *
+ */
+public abstract class Guard extends StateSplit {
+
+    public final Condition condition;
+
+    public Guard(Condition condition, FrameState stateBefore) {
+        super(CiKind.Illegal, stateBefore);
+
+        this.condition = condition;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/IRScope.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,130 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code IRScope} class represents an inlining context in the compilation
+ * of a method.
+ *
+ * @author Ben L. Titzer
+ */
+public class IRScope {
+
+    public final IRScope caller;
+    public final RiMethod method;
+    public final int level;
+    CiCodePos callerCodePos;
+
+    /**
+     * The frame state at the call site of this scope's caller or {@code null}
+     * if this is not a nested scope.
+     */
+    public final FrameState callerState;
+
+    /**
+     * The maximum number of locks held in this scope at any one time
+     * (c.f. maxStack and maxLocals of the Code attribute in a class file).
+     */
+    int maxLocks;
+
+    CiBitMap storesInLoops;
+
+    public IRScope(IRScope caller, FrameState callerState, RiMethod method, int osrBCI) {
+        this.caller = caller;
+        this.callerState = callerState;
+        this.method = method;
+        this.level = caller == null ? 0 : 1 + caller.level;
+    }
+
+    /**
+     * Updates the maximum number of locks held in this scope at any one time.
+     *
+     * @param locks a lock count that will replace the current {@linkplain #maxLocks() max locks} for this scope if it is greater
+     */
+    public void updateMaxLocks(int locks) {
+        if (locks > maxLocks) {
+            maxLocks = locks;
+        }
+    }
+
+    /**
+     * Gets the number of locks in this IR scope.
+     * @return the number of locks
+     */
+    public final int maxLocks() {
+        return maxLocks;
+    }
+
+    /**
+     * Gets the bytecode index of the call site that called this method.
+     * @return the call site's bytecode index
+     */
+    public final int callerBCI() {
+        return callerState == null ? -1 : callerState.bci;
+    }
+
+    /**
+     * Returns whether this IR scope is the top scope (i.e. has no caller).
+     * @return {@code true} if this inlining scope has no parent
+     */
+    public final boolean isTopScope() {
+        return caller == null;
+    }
+
+    /**
+     * Gets the phi bitmap for this IR scope. The phi bitmap stores
+     * whether a phi instruction is required for each local variable.
+     * @return the phi bitmap for this IR scope
+     */
+    public final CiBitMap getStoresInLoops() {
+        return storesInLoops;
+    }
+
+    public final void setStoresInLoops(CiBitMap storesInLoops) {
+        this.storesInLoops = storesInLoops;
+    }
+
+    @Override
+    public String toString() {
+        if (caller == null) {
+            return "root-scope: " + method;
+        } else {
+            return "inlined-scope: " + method + " [caller bci: " + callerState.bci + "]";
+        }
+    }
+
+    public CiCodePos callerCodePos() {
+        if (caller != null && callerCodePos == null) {
+            callerCodePos = caller.toCodePos(callerBCI());
+        }
+        return callerCodePos;
+    }
+
+    public CiCodePos toCodePos(int bci) {
+        return new CiCodePos(callerCodePos(), method, bci);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/If.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,181 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.util.*;
+import com.sun.c1x.value.*;
+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.
+ *
+ * @author Ben L. Titzer
+ */
+public final class If extends BlockEnd {
+
+    Value x;
+    Value y;
+    Condition condition;
+
+    /**
+     * Constructs a new If instruction.
+     * @param x the instruction producing the first input to the instruction
+     * @param cond the condition (comparison operation)
+     * @param unorderedIsTrue {@code true} if unordered is treated as true (floating point operations)
+     * @param y the instruction that produces the second input to this instruction
+     * @param trueSucc the block representing the true successor
+     * @param falseSucc the block representing the false successor
+     * @param stateAfter the state before the branch but after the input values have been popped
+     * @param isSafepoint {@code true} if this branch should be considered a safepoint
+     */
+    public If(Value x, Condition cond, boolean unorderedIsTrue, Value y,
+              BlockBegin trueSucc, BlockBegin falseSucc, FrameState stateAfter, boolean isSafepoint) {
+        super(CiKind.Illegal, stateAfter, isSafepoint);
+        this.x = x;
+        this.y = y;
+        condition = cond;
+        assert Util.archKindsEqual(x, y);
+        initFlag(Flag.UnorderedIsTrue, unorderedIsTrue);
+        successors.add(trueSucc);
+        successors.add(falseSucc);
+    }
+
+    /**
+     * Gets the instruction that produces the first input to this comparison.
+     * @return the instruction producing the first input
+     */
+    public Value x() {
+        return x;
+    }
+
+    /**
+     * Gets the instruction that produces the second input to this comparison.
+     * @return the instruction producing the second input
+     */
+    public Value y() {
+        return y;
+    }
+
+    /**
+     * 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 checkFlag(Flag.UnorderedIsTrue);
+    }
+
+    /**
+     * Gets the block corresponding to the true successor.
+     * @return the true successor
+     */
+    public BlockBegin trueSuccessor() {
+        return successors.get(0);
+    }
+
+    /**
+     * Gets the block corresponding to the false successor.
+     * @return the false successor
+     */
+    public BlockBegin falseSuccessor() {
+        return successors.get(1);
+    }
+
+    /**
+     * 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 BlockBegin successor(boolean istrue) {
+        return successors.get(istrue ? 0 : 1);
+    }
+
+    /**
+     * Gets the successor of this instruction for the unordered case.
+     * @return the successor for unordered inputs
+     */
+    public BlockBegin unorderedSuccessor() {
+        return successor(unorderedIsTrue());
+    }
+
+    /**
+     * Swaps the operands to this if and reverses the condition (e.g. > goes to <=).
+     * @see Condition#mirror()
+     */
+    public void swapOperands() {
+        condition = condition.mirror();
+        Value t = x;
+        x = y;
+        y = t;
+    }
+
+    /**
+     * Swaps the successor blocks to this if and negates the condition (e.g. == goes to !=)
+     * @see Condition#negate()
+     */
+    public void swapSuccessors() {
+        setFlag(Flag.UnorderedIsTrue, !unorderedIsTrue());
+        condition = condition.negate();
+        BlockBegin t = successors.get(0);
+        BlockBegin f = successors.get(1);
+        successors.set(0, f);
+        successors.set(1, t);
+    }
+
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        x = closure.apply(x);
+        y = closure.apply(y);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitIf(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("if ").
+        print(x()).
+        print(' ').
+        print(condition().operator).
+        print(' ').
+        print(y()).
+        print(" then B").
+        print(successors().get(0).blockID).
+        print(" else B").
+        print(successors().get(1).blockID);
+        if (isSafepoint()) {
+            out.print(" (safepoint)");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/IfOp.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,128 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.util.*;
+import com.sun.cri.bytecode.*;
+
+/**
+ * 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.
+ *
+ * @author Ben L. Titzer
+ */
+public final class IfOp extends Op2 {
+
+    Condition cond;
+    Value trueVal;
+    Value falseVal;
+
+    /**
+     * Constructs a new IfOp.
+     * @param x the instruction producing the first value to be compared
+     * @param cond the condition of the comparison
+     * @param y the instruction producing the second value to be compared
+     * @param tval the value produced if the condition is true
+     * @param fval the value produced if the condition is false
+     */
+    public IfOp(Value x, Condition cond, Value y, Value tval, Value fval) {
+        // TODO: return the appropriate bytecode IF_ICMPEQ, etc
+        super(tval.kind.meet(fval.kind), Bytecodes.ILLEGAL, x, y);
+        this.cond = cond;
+        this.trueVal = tval;
+        falseVal = fval;
+    }
+
+    /**
+     * Gets the condition of this if operation.
+     * @return the condition
+     */
+    public Condition condition() {
+        return cond;
+    }
+
+    /**
+     * Gets the instruction that produces the value if the comparison is true.
+     * @return the instruction producing the value upon true
+     */
+    public Value trueValue() {
+        return trueVal;
+    }
+
+    /**
+     * Gets the instruction that produces the value if the comparison is false.
+     * @return the instruction producing the value upon false
+     */
+    public Value falseValue() {
+        return falseVal;
+    }
+
+    /**
+     * 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 cond == Condition.EQ || cond == Condition.NE;
+    }
+
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        super.inputValuesDo(closure);
+        trueVal = closure.apply(trueVal);
+        falseVal = closure.apply(falseVal);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitIfOp(this);
+    }
+
+    @Override
+    public int valueNumber() {
+        return Util.hash4(cond.hashCode(), x, y, trueVal, falseVal);
+    }
+
+    @Override
+    public boolean valueEqual(Instruction i) {
+        if (i instanceof IfOp) {
+            IfOp o = (IfOp) i;
+            return opcode == o.opcode && x == o.x && y == o.y && trueVal == o.trueVal && falseVal == o.falseVal;
+        }
+        return false;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(x()).
+        print(' ').
+        print(condition().operator).
+        print(' ').
+        print(y()).
+        print(" ? ").
+        print(trueValue()).
+        print(" : ").
+        print(falseValue());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/IncrementRegister.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,61 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.cri.ci.*;
+
+/**
+ * @author Doug Simon
+ */
+public final class IncrementRegister extends Instruction {
+
+    public final CiRegister register;
+    private Value delta;
+
+    public IncrementRegister(CiRegister register, Value delta) {
+        super(CiKind.Void);
+        this.register = register;
+        this.delta = delta;
+        setFlag(Flag.LiveStore);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitIncrementRegister(this);
+    }
+
+    public Value delta() {
+        return delta;
+    }
+
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        delta = closure.apply(delta);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(register.toString()).print(" += ").print(delta);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/Info.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,130 @@
+/*
+ * 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.sun.c1x.ir;
+
+import java.util.*;
+
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+
+/**
+ * This class collects a number of debugging and exception-related information about
+ * an HIR node. Instances of this class can be attached to HIR nodes and contain
+ * the {@link com.sun.cri.ci.CiCodePos code position}, the {@link com.sun.c1x.value.FrameState frame state}
+ * potential exceptions, and exception handlers.
+ *
+ * @author Ben L. Titzer
+ */
+public class Info {
+
+    /**
+     * An enumeration of the possible exceptions or stops that an instruction may generate.
+     */
+    public enum StopType {
+        /**
+         * This instruction may throw {@link ArrayIndexOutOfBoundsException}.
+         */
+        java_lang_ArrayOutOfBoundsException,
+
+        /**
+         * This instruction may throw {@link NullPointerException}.
+         */
+        java_lang_NullPointerException,
+
+        /**
+         * This instruction may throw {@link ClassCastException}.
+         */
+        java_lang_ClassCastException,
+
+        /**
+         * This instruction may throw {@link ArrayStoreException}.
+         */
+        java_lang_ArrayStoreException,
+
+        /**
+         * This instruction may throw {@link ArithmeticException}.
+         */
+        java_lang_ArithmeticException,
+
+        /**
+         * This instruction may throw {@link NegativeArraySizeException}.
+         */
+        java_lang_NegativeArraySizeException,
+
+        /**
+         * This instruction may throw {@link OutOfMemoryError}.
+         */
+        java_lang_OutOfMemoryError,
+
+        /**
+         * This instruction may throw {@link IncompatibleClassChangeError}.
+         */
+        java_lang_IncompatibleClassChangeError,
+
+        /**
+         * This instruction may cause a safepoint.
+         */
+        Safepoint,
+
+        /**
+         * This instruction may throw any exception or cause a safepoint.
+         */
+        Unknown;
+
+        public final int mask = 1 << ordinal();
+
+    }
+
+    public final CiCodePos pos;
+    public final int id;
+    private int stopFlags;
+    private FrameState state;
+    private List<ExceptionHandler> exceptionHandlers;
+
+    public Info(CiCodePos pos, int id, FrameState javaFrameState) {
+        this.pos = pos;
+        this.id = id;
+        this.state = javaFrameState;
+    }
+
+    public FrameState frameState() {
+        return state;
+    }
+
+    public boolean mayStop() {
+        return stopFlags != 0;
+    }
+
+    public boolean mayCauseException() {
+        return (stopFlags & ~StopType.Safepoint.mask) != 0;
+    }
+
+    public void clearStop(StopType stopType) {
+        stopFlags &= ~stopType.mask;
+    }
+
+    public void setStop(StopType stopType) {
+        stopFlags |= stopType.mask;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/Infopoint.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,75 @@
+/*
+ * 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.sun.c1x.ir;
+
+import static com.sun.cri.bytecode.Bytecodes.*;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+/**
+ * Records debug info at the current code location.
+ *
+ * @author Doug Simon
+ */
+public final class Infopoint extends Instruction {
+
+    public final FrameState state;
+
+    /**
+     * {@link Bytecodes#HERE}, {@link Bytecodes#INFO} or {@link Bytecodes#SAFEPOINT}.
+     */
+    public final int opcode;
+
+    /**
+     * Creates a new Infopoint instance.
+     * @param state the debug info at this instruction
+     */
+    public Infopoint(int opcode, FrameState state) {
+        super(opcode == HERE ? CiKind.Long : CiKind.Void);
+        assert opcode == HERE || opcode == INFO || opcode == SAFEPOINT : Bytecodes.nameOf(opcode);
+        this.opcode = opcode;
+        this.state = state;
+        setFlag(Flag.LiveSideEffect); // ensure this instruction is not eliminated
+        if (opcode == SAFEPOINT) {
+            setFlag(Value.Flag.IsSafepoint);
+        }
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitInfopoint(this);
+    }
+
+    @Override
+    public FrameState stateBefore() {
+        return state;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(Bytecodes.nameOf(opcode));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/InstanceOf.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,75 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.util.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code InstanceOf} instruction represents an instanceof test.
+ *
+ * @author Ben L. Titzer
+ */
+public final class InstanceOf extends TypeCheck {
+
+    /**
+     * 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 stateBefore the state before this instruction
+     */
+    public InstanceOf(RiType targetClass, Value targetClassInstruction, Value object, FrameState stateBefore) {
+        super(targetClass, targetClassInstruction, object, CiKind.Int, stateBefore);
+        if (object.isNonNull()) {
+            eliminateNullCheck();
+        }
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitInstanceOf(this);
+    }
+
+    @Override
+    public int valueNumber() {
+        return Util.hash1(Bytecodes.INSTANCEOF, object);
+    }
+
+    @Override
+    public boolean valueEqual(Instruction i) {
+        if (i instanceof InstanceOf) {
+            InstanceOf o = (InstanceOf) i;
+            return targetClass == o.targetClass && object == o.object;
+        }
+        return false;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("instanceof(").print(object()).print(") ").print(CiUtil.toJavaName(targetClass()));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/Instruction.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,266 @@
+/*
+ * 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.sun.c1x.ir;
+
+import java.util.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+
+/**
+ * Denotes an instruction node in the IR, which is a {@link Value} that
+ * can be added to a basic block (whereas other {@link Value} nodes such as {@link Phi} and
+ * {@link Local} cannot be added to basic blocks).
+ *
+ * Subclasses of instruction represent arithmetic and object operations,
+ * control flow operators, phi statements, method calls, the start of basic blocks, and
+ * the end of basic blocks.
+ *
+ * Instruction nodes are chained together in a basic block through the embedded
+ * {@link Instruction#next} field. An Instruction may also have a list of {@link ExceptionHandler}s.
+ *
+ *
+ * @author Ben L. Titzer
+ */
+public abstract class Instruction extends Value {
+
+    public static final int INVOCATION_ENTRY_BCI = -1;  // XXX: not currently used
+    public static final int SYNCHRONIZATION_ENTRY_BCI = -1;
+
+    /**
+     * Index of bytecode that generated this node when appended in a basic block.
+     * Negative values indicate special cases.
+     */
+    private int bci;
+
+    /**
+     * Links to next instruction in a basic block or to {@code} itself if not in a block.
+     */
+    private Instruction next = this;
+
+    /**
+     * List of associated exception handlers.
+     */
+    private List<ExceptionHandler> exceptionHandlers = ExceptionHandler.ZERO_HANDLERS;
+
+    /**
+     * Constructs a new instruction with the specified value type.
+     * @param kind the value type for this instruction
+     */
+    public Instruction(CiKind kind) {
+        super(kind);
+        C1XMetrics.HIRInstructions++;
+    }
+
+    /**
+     * Gets the bytecode index of this instruction.
+     * @return the bytecode index of this instruction
+     */
+    public final int bci() {
+        return bci;
+    }
+
+    /**
+     * Sets the bytecode index of this instruction.
+     * @param bci the new bytecode index for this instruction
+     */
+    public final void setBCI(int bci) {
+        assert bci >= 0 || bci == SYNCHRONIZATION_ENTRY_BCI;
+        this.bci = bci;
+    }
+
+    /**
+     * Checks whether this instruction has already been added to its basic block.
+     * @return {@code true} if this instruction has been added to the basic block containing it
+     */
+    public final boolean isAppended() {
+        return next != this;
+    }
+
+    /**
+     * Gets the next instruction after this one in the basic block, or {@code null}
+     * if this instruction is the end of a basic block.
+     * @return the next instruction after this one in the basic block
+     */
+    public final Instruction next() {
+        if (next == this) {
+            return null;
+        }
+        return next;
+    }
+
+    /**
+     * Sets the next instruction for this instruction. Note that it is illegal to
+     * set the next field of a phi, block end, or local instruction.
+     * @param next the next instruction
+     * @param bci the bytecode index of the next instruction
+     * @return the new next instruction
+     */
+    public final Instruction setNext(Instruction next, int bci) {
+        this.next = next;
+        if (next != null) {
+            assert !(this instanceof BlockEnd);
+            next.setBCI(bci);
+            if (next.next == next) {
+                next.next = null;
+            }
+        }
+        return next;
+    }
+
+    /**
+     * Re-sets the next instruction for this instruction. Note that it is illegal to
+     * set the next field of a phi, block end, or local instruction.
+     * @param next the next instruction
+     * @return the new next instruction
+     */
+    public final Instruction resetNext(Instruction next) {
+        if (next != null) {
+            assert !(this instanceof BlockEnd);
+            this.next = next;
+        }
+        return next;
+    }
+
+    /**
+     * Gets the instruction preceding this instruction in the specified basic block.
+     * Note that instructions do not directly refer to their previous instructions,
+     * and therefore this operation much search from the beginning of the basic
+     * block, thereby requiring time linear in the size of the basic block in the worst
+     * case. Use with caution!
+     * @param block the basic block that contains this instruction
+     * @return the instruction before this instruction in the basic block
+     */
+    public final Instruction prev(BlockBegin block) {
+        Instruction p = null;
+        Instruction q = block;
+        while (q != this) {
+            assert q != null : "this instruction is not in the specified basic block";
+            p = q;
+            q = q.next();
+        }
+        return p;
+    }
+
+    @Override
+    public BlockBegin block() {
+        // TODO(tw): Make this more efficient.
+        Instruction cur = this;
+        while (!(cur instanceof BlockEnd)) {
+            cur = cur.next;
+        }
+        return ((BlockEnd) cur).begin;
+    }
+
+    /**
+     * Gets the list of exception handlers associated with this instruction.
+     * @return the list of exception handlers for this instruction
+     */
+    public final List<ExceptionHandler> exceptionHandlers() {
+        return exceptionHandlers;
+    }
+
+    /**
+     * Sets the list of exception handlers for this instruction.
+     * @param exceptionHandlers the exception handlers
+     */
+    public final void setExceptionHandlers(List<ExceptionHandler> exceptionHandlers) {
+        this.exceptionHandlers = exceptionHandlers;
+    }
+
+    /**
+     * Compute the value number of this Instruction. Local and global value numbering
+     * optimizations use a hash map, and the value number provides a hash code.
+     * If the instruction cannot be value numbered, then this method should return
+     * {@code 0}.
+     * @return the hashcode of this instruction
+     */
+    public int valueNumber() {
+        return 0;
+    }
+
+    /**
+     * Checks that this instruction is equal to another instruction for the purposes
+     * of value numbering.
+     * @param i the other instruction
+     * @return {@code true} if this instruction is equivalent to the specified
+     * instruction w.r.t. value numbering
+     */
+    public boolean valueEqual(Instruction i) {
+        return false;
+    }
+
+    /**
+     * Gets the name of this instruction as a string.
+     * @return the name of this instruction
+     */
+    public final String name() {
+        return getClass().getSimpleName();
+    }
+
+    /**
+     * Tests whether this instruction can trap. This is conservative; it does not take
+     * into account analysis results that may eliminate the possibility of this
+     * instruction from trapping.
+     *
+     * @return {@code true} if this instruction can cause a trap.
+     */
+    public boolean canTrap() {
+        return false;
+    }
+
+    /**
+     * Apply the specified closure to all the values of this instruction, including
+     * input values, state values, and other values.
+     * @param closure the closure to apply
+     */
+    public final void allValuesDo(ValueClosure closure) {
+        inputValuesDo(closure);
+        FrameState stateBefore = stateBefore();
+        if (stateBefore != null) {
+            stateBefore.valuesDo(closure);
+        }
+        FrameState stateAfter = stateAfter();
+        if (stateAfter != null) {
+            stateAfter.valuesDo(closure);
+        }
+    }
+
+    /**
+     * Gets the state before the instruction, if it is recorded.
+     * @return the state before the instruction
+     */
+    public FrameState stateBefore() {
+        return null;
+    }
+
+    /**
+     * Gets the state after the instruction, if it is recorded. Typically only
+     * instances of {@link BlockEnd} have a non-null state after.
+     * @return the state after the instruction
+     */
+    public FrameState stateAfter() {
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/Intrinsic.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,178 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.*;
+import com.sun.c1x.debug.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code Intrinsic} instruction represents a call to a JDK method
+ * that has been made {@linkplain C1XIntrinsic intrinsic}.
+ *
+ * @author Ben L. Titzer
+ * @see C1XIntrinsic
+ */
+public final class Intrinsic extends StateSplit {
+
+    final C1XIntrinsic intrinsic;
+    final RiMethod target;
+    final Value[] arguments;
+    final boolean canTrap;
+
+    /**
+     * Creates a new Intrinsic instruction.
+     * @param kind the result type of the instruction
+     * @param intrinsic the actual intrinsic
+     * @param target the method for this intrinsic
+     * @param args the arguments to the call (including the receiver object)
+     * @param isStatic {@code true} if this method is static
+     * @param stateBefore the lock stack
+     * @param preservesState {@code true} if the implementation of this intrinsic preserves register state
+     * @param canTrap {@code true} if this intrinsic can cause a trap
+     */
+    public Intrinsic(CiKind kind, C1XIntrinsic intrinsic, RiMethod target, Value[] args, boolean isStatic,
+                     FrameState stateBefore, boolean preservesState, boolean canTrap) {
+        super(kind, stateBefore);
+        this.intrinsic = intrinsic;
+        int nonNullArgs = 0;
+        for (int i = 0; i < args.length; ++i) {
+            if (args[i] != null) {
+                nonNullArgs++;
+            }
+        }
+        this.arguments = new Value[nonNullArgs];
+        int z = 0;
+        for (int i = 0; i < args.length; ++i) {
+            if (args[i] != null) {
+                arguments[z++] = args[i];
+            }
+        }
+        this.target = target;
+        initFlag(Flag.IsStatic, isStatic);
+        // Preserves state means that the intrinsic preserves register state across all cases,
+        // including slow cases--even if it causes a trap. If so, it can still be a candidate
+        // for load elimination and common subexpression elimination
+        initFlag(Flag.PreservesState, preservesState);
+        this.canTrap = canTrap;
+        if (!isStatic && args[0].isNonNull()) {
+            eliminateNullCheck();
+        }
+    }
+
+    /**
+     * Gets the intrinsic represented by this instruction.
+     * @return the intrinsic
+     */
+    public C1XIntrinsic intrinsic() {
+        return intrinsic;
+    }
+
+    /**
+     * Gets the target method for this invocation instruction.
+     * @return the target method
+     */
+    public RiMethod target() {
+        return target;
+    }
+
+    /**
+     * Gets the list of instructions that produce input for this instruction.
+     * @return the list of instructions that produce input
+     */
+    public Value[] arguments() {
+        return arguments;
+    }
+
+    public boolean isStatic() {
+        return checkFlag(Flag.IsStatic);
+    }
+
+    /**
+     * Checks whether this intrinsic has a receiver object.
+     * @return {@code true} if this intrinsic has a receiver object
+     */
+    public boolean hasReceiver() {
+        return !isStatic();
+    }
+
+    /**
+     * Gets the instruction which produces the receiver object for this intrinsic.
+     * @return the instruction producing the receiver object
+     */
+    public Value receiver() {
+        assert !isStatic();
+        return arguments[0];
+    }
+
+    /**
+     * Checks whether this intrinsic preserves the state of registers across all cases.
+     * @return {@code true} if this intrinsic always preserves register state
+     */
+    public boolean preservesState() {
+        return checkFlag(Flag.PreservesState);
+    }
+
+    /**
+     * Checks whether this intrinsic can cause a trap.
+     * @return {@code true} if this intrinsic can cause a trap
+     */
+    @Override
+    public boolean canTrap() {
+        return canTrap;
+    }
+
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        for (int i = 0; i < arguments.length; i++) {
+            arguments[i] = closure.apply(arguments[i]);
+        }
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitIntrinsic(this);
+    }
+
+    public Value argumentAt(int i) {
+        return arguments[i];
+    }
+
+    public int numberOfArguments() {
+        return arguments.length;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(intrinsic().className).print('.').print(intrinsic().name()).print('(');
+        for (int i = 0; i < arguments().length; i++) {
+          if (i > 0) {
+              out.print(", ");
+          }
+          out.print(arguments()[i]);
+        }
+        out.print(')');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/Invoke.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,172 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.util.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code Invoke} instruction represents all kinds of method calls.
+ *
+ * @author Ben L. Titzer
+ */
+public final class Invoke extends StateSplit {
+
+    public final int opcode;
+    public final Value[] arguments;
+    public final RiMethod target;
+    public final RiType returnType;
+
+    /**
+     * 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
+     * @param stateBefore the state before executing the invocation
+     */
+    public Invoke(int opcode, CiKind result, Value[] args, boolean isStatic, RiMethod target, RiType returnType, FrameState stateBefore) {
+        super(result, stateBefore);
+        this.opcode = opcode;
+        this.arguments = args;
+        this.target = target;
+        this.returnType = returnType;
+        if (isStatic) {
+            setFlag(Flag.IsStatic);
+            eliminateNullCheck();
+        } else if (args[0].isNonNull() || args[0].kind.isWord()) {
+            eliminateNullCheck();
+        }
+    }
+
+    /**
+     * 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 checkFlag(Flag.IsStatic);
+    }
+
+    @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[0];
+    }
+
+    /**
+     * Gets the target method for this invocation instruction.
+     * @return the target method
+     */
+    public RiMethod target() {
+        return target;
+    }
+
+    /**
+     * Gets the list of instructions that produce input for this instruction.
+     * @return the list of instructions that produce input
+     */
+    public Value[] arguments() {
+        return arguments;
+    }
+
+    /**
+     * Checks whether this instruction can trap.
+     * @return {@code true}, conservatively assuming the called method may throw an exception
+     */
+    @Override
+    public boolean canTrap() {
+        return true;
+    }
+
+    /**
+     * 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 inputValuesDo(ValueClosure closure) {
+        for (int i = 0; i < arguments.length; i++) {
+            Value arg = arguments[i];
+            if (arg != null) {
+                arguments[i] = closure.apply(arg);
+                assert arguments[i] != null;
+            }
+        }
+    }
+
+    @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('(');
+        Value[] arguments = arguments();
+        for (int i = argStart; i < arguments.length; i++) {
+            if (i > argStart) {
+                out.print(", ");
+            }
+            out.print(arguments[i]);
+        }
+        out.print(CiUtil.format(") [method: %H.%n(%p):%r]", target, false));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/LoadField.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.ir;
+
+import com.sun.c1x.*;
+import com.sun.c1x.debug.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code LoadField} instruction represents a read of a static or instance field.
+ *
+ * @author Ben L. Titzer
+ */
+public final class LoadField extends AccessField {
+
+    /**
+     * 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 stateBefore the state before the field access
+     * @param isLoaded indicates if the class is loaded
+     */
+    public LoadField(Value object, RiField field, boolean isStatic, FrameState stateBefore, boolean isLoaded) {
+        super(field.kind().stackKind(), object, field, isStatic, stateBefore, isLoaded);
+    }
+
+    /**
+     * 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 declaredType = declaredType();
+        return declaredType.isResolved() ? declaredType.exactType() : null;
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitLoadField(this);
+    }
+
+    /**
+     * Gets a constant value to which this load can be reduced.
+     *
+     * @return {@code null} if this load cannot be reduced to a constant
+     */
+    public CiConstant constantValue() {
+        if (!C1XOptions.CanonicalizeConstantFields) {
+            return null;
+        }
+        if (isStatic()) {
+            return field.constantValue(null);
+        } else if (object().isConstant()) {
+            CiConstant cons = field.constantValue(object().asConstant());
+            if (cons != null) {
+                return cons;
+            }
+            return cons;
+        }
+        return null;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(object()).
+        print(".").
+        print(field.name()).
+        print(" [field: ").
+        print(CiUtil.format("%h.%n:%t", field, false)).
+        print("]");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/LoadIndexed.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code LoadIndexed} instruction represents a read from an element of an array.
+ *
+ * @author Ben L. Titzer
+ */
+public final class LoadIndexed extends AccessIndexed {
+
+    /**
+     * 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 elementType the element type
+     * @param stateBefore the state before executing this instruction
+     */
+    public LoadIndexed(Value array, Value index, Value length, CiKind elementType, FrameState stateBefore) {
+        super(elementType.stackKind(), array, index, length, elementType, stateBefore);
+    }
+
+    /**
+     * 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(')');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/LoadPointer.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code LoadPointer} instruction represents a read of a pointer.
+ * This instruction is part of the HIR support for low-level operations, such as safepoints,
+ * stack banging, etc, and does not correspond to a Java operation.
+ *
+ * @author Ben L. Titzer
+ * @author Doug Simon
+ */
+public final class LoadPointer extends PointerOp {
+
+    /**
+     * Creates an instruction for a pointer load.
+     *
+     * @param kind the kind of value loaded from the pointer
+     * @param opcode the opcode of the instruction
+     * @param pointer the value producing the pointer
+     * @param displacement the value producing the displacement. This may be {@code null}.
+     * @param offsetOrIndex the value producing the scaled-index or the byte offset depending on whether {@code displacement} is {@code null}
+     * @param stateBefore the state before
+     * @param isVolatile {@code true} if the access is volatile
+     * @see PointerOp#PointerOp(CiKind, int, Value, Value, Value, FrameState, boolean)
+     */
+    public LoadPointer(CiKind kind, int opcode, Value pointer, Value displacement, Value offsetOrIndex, FrameState stateBefore, boolean isVolatile) {
+        super(kind, kind, opcode, pointer, displacement, offsetOrIndex, stateBefore, isVolatile);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitLoadPointer(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("*(").print(pointer());
+        if (displacement() == null) {
+            out.print(" + ").print(offset());
+        } else {
+            out.print(" + ").print(displacement()).print(" + (").print(index()).print(" * sizeOf(" + dataKind + "))");
+        }
+        out.print(")");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/LoadRegister.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,58 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code LoadRegister} instruction represents a read of a physical register.
+ * This instruction is part of the HIR support for low-level operations, such as safepoints,
+ * stack banging, etc, and does not correspond to a Java operation.
+ *
+ * @author Ben L. Titzer
+ */
+public final class LoadRegister extends Instruction {
+
+    public final CiRegister register;
+
+    /**
+     * Creates a new LoadRegister instance.
+     * @param kind the kind of value loaded from the register
+     * @param register the register to load
+     */
+    public LoadRegister(CiKind kind, CiRegister register) {
+        super(kind);
+        this.register = register;
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitLoadRegister(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(register.toString());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/Local.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,84 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+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.
+ *
+ * @author Ben L. Titzer
+ */
+public final class Local extends Value {
+
+    private final int javaIndex;
+    private RiType declaredType;
+
+    public Local(CiKind kind, int javaIndex) {
+        super(kind);
+        this.javaIndex = javaIndex;
+    }
+
+    @Override
+    public BlockBegin block() {
+        return null;
+    }
+
+    /**
+     * Gets the index of this local.
+     * @return the index
+     */
+    public int javaIndex() {
+        return javaIndex;
+    }
+
+    /**
+     * 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(javaIndex()).print(']');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/LogicOp.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code LogicOp} class definition.
+ *
+ * @author Ben L. Titzer
+ */
+public final class LogicOp extends Op2 {
+
+    /**
+     * Constructs a new logic operation instruction.
+     * @param opcode the opcode of the logic operation
+     * @param x the first input into this instruction
+     * @param s the second input into this instruction
+     */
+    public LogicOp(int opcode, Value x, Value s) {
+        super(x.kind, opcode, x, s);
+    }
+
+    public LogicOp(CiKind kind, int opcode, Value x, Value s) {
+        super(kind, opcode, x, s);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitLogicOp(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(x()).print(' ').print(Bytecodes.operator(opcode)).print(' ').print(y());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/LookupSwitch.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,88 @@
+/*
+ * 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.sun.c1x.ir;
+
+import static com.sun.c1x.debug.InstructionPrinter.InstructionLineColumn.*;
+
+import java.util.*;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.value.*;
+
+/**
+ * The {@code LookupSwitch} instruction represents a lookup switch bytecode, which has a sorted
+ * array of key values.
+ *
+ * @author Ben L. Titzer
+ */
+public final class LookupSwitch extends Switch {
+
+    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 stateBefore the state before the switch
+     * @param isSafepoint {@code true} if this instruction is a safepoint
+     */
+    public LookupSwitch(Value value, List<BlockBegin> successors, int[] keys, FrameState stateBefore, boolean isSafepoint) {
+        super(value, successors, stateBefore, isSafepoint);
+        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 ");
+        if (isSafepoint()) {
+            out.print("(safepoint) ");
+        }
+        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), successors().get(i).blockID);
+        }
+        INSTRUCTION.advance(out);
+        out.print("default   : B").print(defaultSuccessor().blockID);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/MemoryBarrier.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,61 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.bytecode.Bytecodes.*;
+import com.sun.cri.ci.*;
+
+/**
+ * Instruction implementing the semantics of {@link Bytecodes#MEMBAR}.
+ *
+ * @author Doug Simon
+ */
+public final class MemoryBarrier extends Instruction {
+
+    /**
+     * A mask of the constants defined by {@link Bytecodes.MemoryBarriers}.
+     */
+    public final int barriers;
+
+    /**
+     * Creates a {@link MemoryBarrier} instance.
+     */
+    public MemoryBarrier(int barriers) {
+        super(CiKind.Void);
+        assert barriers != 0;
+        this.barriers = barriers;
+        setFlag(Flag.LiveSideEffect);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitMemoryBarrier(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(MemoryBarriers.barriersString(barriers));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/MonitorAddress.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,57 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.cri.ci.*;
+
+/**
+ * Instruction that is used to refer to the address of an on-stack monitor.
+ *
+ * @author Lukas Stadler
+ */
+public final class MonitorAddress extends Instruction {
+
+    private int monitor;
+
+    public MonitorAddress(int monitor) {
+        super(CiKind.Word);
+        this.monitor = monitor;
+        setFlag(Flag.NonNull);
+        eliminateNullCheck();
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitMonitorAddress(this);
+    }
+
+    public int monitor() {
+        return monitor;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("monitor_address (").print(monitor()).print(")");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/MonitorEnter.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,79 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.value.*;
+
+/**
+ * The {@code MonitorEnter} instruction represents the acquisition of a monitor.
+ *
+ * @author Ben L. Titzer
+ */
+public final class MonitorEnter extends AccessMonitor {
+
+    private FrameState stateAfter;
+
+    /**
+     * 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 stateBefore the state before
+     */
+    public MonitorEnter(Value object, Value lockAddress, int lockNumber, FrameState stateBefore) {
+        super(object, lockAddress, stateBefore, lockNumber);
+        if (object.isNonNull()) {
+            eliminateNullCheck();
+        }
+    }
+
+    /**
+     * Checks whether this instruction can trap.
+     * @return {@code true} if this instruction may raise a {@link NullPointerException}
+     */
+    @Override
+    public boolean canTrap() {
+        return needsNullCheck();
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitMonitorEnter(this);
+    }
+
+    public void setStateAfter(FrameState frameState) {
+        this.stateAfter = frameState;
+    }
+
+    @Override
+    public FrameState stateAfter() {
+        return stateAfter;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("enter monitor[").print(lockNumber).print("](").print(object()).print(')');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/MonitorExit.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,66 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.value.*;
+
+/**
+ * The {@code MonitorExit} instruction represents a monitor release.
+ *
+ * @author Ben L. Titzer
+ */
+public final class MonitorExit extends AccessMonitor {
+
+    /**
+     * 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 stateBefore the state before executing this instruction
+     */
+    public MonitorExit(Value object, Value lockAddress, int lockNumber, FrameState stateBefore) {
+        super(object, lockAddress, stateBefore, lockNumber);
+        if (object.isNonNull()) {
+            eliminateNullCheck();
+        }
+    }
+
+    @Override
+    public boolean canTrap() {
+        // C1X assumes that locks are well balanced and so there no need to handle
+        // IllegalMonitorStateExceptions thrown by monitorexit instructions.
+        return needsNullCheck();
+    }
+
+    @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(')');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/NativeCall.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,119 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.ri.*;
+
+/**
+ * Represents a call to a native function from within a native method stub.
+ *
+ * @author Doug Simon
+ */
+public final class NativeCall extends StateSplit {
+
+    /**
+     * The instruction that produces the native function address for this native call.
+     */
+    private Value address;
+
+    /**
+     * The native method for this native call.
+     */
+    public final RiMethod nativeMethod;
+
+    /**
+     * The signature of the call which is derived from {@link #nativeMethod} but is not
+     * the same as its {@linkplain RiMethod#signature() signature}.
+     */
+    public final RiSignature signature;
+
+    /**
+     * The list of instructions that produce the arguments for this native call.
+     */
+    public final Value[] arguments;
+
+    /**
+     * Constructs a new NativeCall instruction.
+     *
+     * @param nativeMethod TODO
+     * @param signature TODO
+     * @param address TODO
+     * @param args the list of instructions producing arguments to the invocation
+     * @param stateBefore the state before executing the invocation
+     */
+    public NativeCall(RiMethod nativeMethod, RiSignature signature, Value address, Value[] args, FrameState stateBefore) {
+        super(signature.returnKind().stackKind(), stateBefore);
+        this.address = address;
+        this.nativeMethod = nativeMethod;
+        this.arguments = args;
+        this.signature = signature;
+        assert nativeMethod.jniSymbol() != null;
+    }
+
+    /**
+     * The native function may call back into the VM which may call method that can trap.
+     */
+    @Override
+    public boolean canTrap() {
+        return true;
+    }
+
+    /**
+     * Gets the instruction that produces the native function address for this native call.
+     * @return the instruction
+     */
+    public Value address() {
+        return address;
+    }
+
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        for (int i = 0; i < arguments.length; i++) {
+            Value arg = arguments[i];
+            if (arg != null) {
+                arguments[i] = closure.apply(arg);
+                assert arguments[i] != null;
+            }
+        }
+        address = closure.apply(address);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitNativeCall(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(nativeMethod.jniSymbol()).print('(');
+        for (int i = 0; i < arguments.length; i++) {
+            if (i > 0) {
+                out.print(", ");
+            }
+            out.print(arguments[i]);
+        }
+        out.print(')');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/NegateOp.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,83 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.util.*;
+import com.sun.cri.bytecode.*;
+
+/**
+ * The {@code NegateOp} instruction negates its operand.
+ *
+ * @author Ben L. Titzer
+ */
+public final class NegateOp extends Instruction {
+
+    Value x;
+
+    /**
+     * Creates new NegateOp instance.
+     * @param x the instruction producing the value that is input to this instruction
+     */
+    public NegateOp(Value x) {
+        super(x.kind);
+        this.x = x;
+    }
+
+    /**
+     * Gets the instruction producing input to this instruction.
+     * @return the instruction that produces this instruction's input
+     */
+    public Value x() {
+        return x;
+    }
+
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        x = closure.apply(x);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitNegateOp(this);
+    }
+
+    @Override
+    public int valueNumber() {
+        return Util.hash1(Bytecodes.INEG, x);
+    }
+
+    @Override
+    public boolean valueEqual(Instruction i) {
+        if (i instanceof NegateOp) {
+            NegateOp o = (NegateOp) i;
+            return x == o.x;
+        }
+        return false;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("- ").print(x());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/NewArray.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,75 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code NewArray} class is the base of all instructions that allocate arrays.
+ *
+ * @author Ben L. Titzer
+ */
+public abstract class NewArray extends StateSplit {
+
+    Value length;
+
+    /**
+     * Constructs a new NewArray instruction.
+     * @param length the instruction that produces the length for this allocation
+     * @param stateBefore the state before the allocation
+     */
+    NewArray(Value length, FrameState stateBefore) {
+        super(CiKind.Object, stateBefore);
+        this.length = length;
+        setFlag(Flag.NonNull);
+        setFlag(Flag.ResultIsUnique);
+    }
+
+    /**
+     * Gets the instruction that produces the length of this array.
+     * @return the instruction that produces the length
+     */
+    public Value length() {
+        return length;
+    }
+
+    /**
+     * Checks whether this instruction can trap.
+     * @return <code>true</code>, conservatively assuming that this instruction can throw such
+     * exceptions as {@code OutOfMemoryError}
+     */
+    @Override
+    public boolean canTrap() {
+        return true;
+    }
+
+    /**
+     * Applies the specified closure to all input values of this instruction.
+     * @param closure the closure to apply
+     */
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        length = closure.apply(length);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/NewInstance.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code NewInstance} instruction represents the allocation of an instance class object.
+ *
+ * @author Ben L. Titzer
+ */
+public final class NewInstance extends StateSplit {
+
+    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 stateBefore the state before executing this instruction
+     */
+    public NewInstance(RiType type, int cpi, RiConstantPool constantPool, FrameState stateBefore) {
+        super(CiKind.Object, stateBefore);
+        this.instanceClass = type;
+        this.cpi = cpi;
+        this.constantPool = constantPool;
+        setFlag(Flag.NonNull);
+        setFlag(Flag.ResultIsUnique);
+    }
+
+    /**
+     * Gets the instance class being allocated by this instruction.
+     * @return the instance class allocated
+     */
+    public RiType instanceClass() {
+        return instanceClass;
+    }
+
+    /**
+     * Checks whether this instruction can trap.
+     * @return {@code true}, assuming that allocation can cause OutOfMemory or other exceptions
+     */
+    @Override
+    public boolean canTrap() {
+        return true;
+    }
+
+    /**
+     * 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()));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/NewMultiArray.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code NewMultiArray} instruction represents an allocation of a multi-dimensional object
+ * array.
+ *
+ * @author Ben L. Titzer
+ */
+public final class NewMultiArray extends NewArray {
+    public final RiType elementKind;
+    final Value[] dimensions;
+    public final int cpi;
+    public final RiConstantPool constantPool;
+
+    /**
+     * Constructs a new NewMultiArray instruction.
+     * @param elementKind the element type of the array
+     * @param dimensions the instructions which produce the dimensions for this array
+     * @param stateBefore the state before this instruction
+     * @param cpi the constant pool index for resolution
+     * @param riConstantPool the constant pool for resolution
+     */
+    public NewMultiArray(RiType elementKind, Value[] dimensions, FrameState stateBefore, int cpi, RiConstantPool riConstantPool) {
+        super(null, stateBefore);
+        this.constantPool = riConstantPool;
+        this.elementKind = elementKind;
+        this.dimensions = dimensions;
+        this.cpi = cpi;
+    }
+
+    /**
+     * Gets the list of instructions which produce input for this instruction.
+     * @return the list of instructions which produce input
+     */
+    public Value[] dimensions() {
+        return dimensions;
+    }
+
+    /**
+     * Gets the rank of the array allocated by this instruction, i.e. how many array dimensions.
+     * @return the rank of the array allocated
+     */
+    public int rank() {
+        return dimensions.length;
+    }
+
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        for (int i = 0; i < dimensions.length; i++) {
+            dimensions[i] = closure.apply(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 elementKind;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("new multi array [");
+        final Value[] dimensions = dimensions();
+        for (int i = 0; i < dimensions.length; i++) {
+          if (i > 0) {
+              out.print(", ");
+          }
+          out.print(dimensions[i]);
+        }
+        out.print("] ").print(CiUtil.toJavaName(elementKind));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/NewObjectArray.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code NewObjectArray} instruction represents an allocation of an object array.
+ *
+ * @author Ben L. Titzer
+ */
+public final class NewObjectArray extends NewArray {
+
+    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 stateBefore the state before the allocation
+     */
+    public NewObjectArray(RiType elementClass, Value length, FrameState stateBefore) {
+        super(length, stateBefore);
+        this.elementClass = elementClass;
+    }
+
+    /**
+     * Gets the type of the elements of the array.
+     * @return the element type of the array
+     */
+    public RiType elementClass() {
+        return elementClass;
+    }
+
+    @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(elementClass()));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/NewObjectArrayClone.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code NewObjectArray} instruction represents an allocation of an object array.
+ *
+ * @author Thomas Wuerthinger
+ */
+public final class NewObjectArrayClone extends NewArray {
+
+    final Value referenceArray;
+
+    /**
+     * Constructs a new NewObjectArray instruction.
+     * @param length the instruction producing the length of the array
+     * @param referenceArray
+     * @param stateBefore the state before the allocation
+     */
+    public NewObjectArrayClone(Value length, Value referenceArray, FrameState stateBefore) {
+        super(length, stateBefore);
+        this.referenceArray = referenceArray;
+    }
+
+    @Override
+    public RiType exactType() {
+        return referenceArray.exactType();
+    }
+
+    @Override
+    public RiType declaredType() {
+        return referenceArray.declaredType();
+    }
+
+    public Value referenceArray() {
+        return referenceArray;
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitNewObjectArrayClone(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("new object array [").print(length()).print("] ").print(referenceArray());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/NewTypeArray.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,67 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code NewTypeArray} class definition.
+ *
+ * @author Ben L. Titzer
+ */
+public final class NewTypeArray extends NewArray {
+
+    final RiType elementType;
+
+    public NewTypeArray(Value length, RiType elementType, FrameState stateBefore) {
+        super(length, stateBefore);
+        this.elementType = elementType;
+    }
+
+    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(']');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/NullCheck.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,119 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.util.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code NullCheck} class represents an explicit null check instruction.
+ *
+ * @author Ben L. Titzer
+ */
+public final class NullCheck extends StateSplit {
+
+    Value object;
+
+    /**
+     * Constructs a new NullCheck instruction.
+     * @param obj the instruction producing the object to check against null
+     * @param stateBefore the state before executing the null check
+     */
+    public NullCheck(Value obj, FrameState stateBefore) {
+        super(obj.kind, stateBefore);
+        this.object = obj;
+        setFlag(Flag.NonNull);
+        if (object.isNonNull()) {
+            eliminateNullCheck();
+        }
+    }
+
+    /**
+     * Gets the instruction that produces the object tested against null.
+     * @return the instruction producing the object
+     */
+    public Value object() {
+        return object;
+    }
+
+    /**
+     * Checks whether this instruction can cause a trap.
+     * @return {@code true} if this instruction can cause a trap
+     */
+    @Override
+    public boolean canTrap() {
+        return needsNullCheck();
+    }
+
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        object = closure.apply(object);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitNullCheck(this);
+    }
+
+    @Override
+    public int valueNumber() {
+        return Util.hash1(Bytecodes.IFNONNULL, object);
+    }
+
+    @Override
+    public boolean valueEqual(Instruction i) {
+        if (i instanceof NullCheck) {
+            NullCheck o = (NullCheck) i;
+            return object == o.object;
+        }
+        return false;
+    }
+
+    @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 runtimeCheckCleared() {
+        clearState();
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("null_check(").print(object()).print(')');
+        if (!canTrap()) {
+          out.print(" (eliminated)");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/Op2.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.ir;
+
+import com.sun.c1x.util.*;
+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.
+ *
+ * @author Ben L. Titzer
+ */
+public abstract class Op2 extends Instruction {
+
+    /**
+     * The opcode of this instruction.
+     */
+    public final int opcode;
+
+    Value x;
+    Value y;
+
+    /**
+     * 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 Op2(CiKind kind, int opcode, Value x, Value y) {
+        super(kind);
+        this.opcode = opcode;
+        this.x = x;
+        this.y = y;
+    }
+
+    /**
+     * Gets the first input to this instruction.
+     * @return the first input to this instruction
+     */
+    public final Value x() {
+        return x;
+    }
+
+    /**
+     * Gets the second input to this instruction.
+     * @return the second input to this instruction
+     */
+    public final Value y() {
+        return y;
+    }
+
+    /**
+     * Swaps the operands of this instruction. This is only legal for commutative operations.
+     */
+    public void swapOperands() {
+        assert Bytecodes.isCommutative(opcode);
+        Value t = x;
+        x = y;
+        y = t;
+    }
+
+    /**
+     * Iterates over the inputs to this instruction.
+     * @param closure the closure to apply to each input value
+     */
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        x = closure.apply(x);
+        y = closure.apply(y);
+    }
+
+    @Override
+    public int valueNumber() {
+        return Util.hash2(opcode, x, y);
+    }
+
+    @Override
+    public boolean valueEqual(Instruction i) {
+        if (i instanceof Op2) {
+            Op2 o = (Op2) 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/Compiler/src/com/sun/c1x/ir/OsrEntry.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,52 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code OsrEntry} instruction represents the buffer for an OSR.
+ *
+ * @author Ben L. Titzer
+ */
+public final class OsrEntry extends Instruction {
+
+    /**
+     * Constructs a new OsrEntry instruction.
+     */
+    public OsrEntry() {
+        // TODO: this should be a CiKind.Word
+        super(CiKind.Jsr);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitOsrEntry(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("osr entry");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/Pause.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,53 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+/**
+ * Instruction implementing the semantics of {@link Bytecodes#PAUSE}.
+ *
+ * @author Doug Simon
+ */
+public final class Pause extends Instruction {
+
+    /**
+     * Creates a {@link Pause} instance.
+     */
+    public Pause() {
+        super(CiKind.Void);
+        setFlag(Flag.LiveSideEffect); // ensure this instruction is not eliminated
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitPause(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("pause");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/Phi.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,153 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.value.*;
+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.
+ *
+ * @author Ben L. Titzer
+ */
+public final class Phi extends Value {
+
+    private final BlockBegin block;
+    private final int index;
+
+    /**
+     * Create a new Phi for the specified join block and local variable (or operand stack) slot.
+     * @param kind the type of the variable
+     * @param block the join point
+     * @param index the index into the stack (if < 0) or local variables
+     */
+    public Phi(CiKind kind, BlockBegin block, int index) {
+        super(kind);
+        this.block = block;
+        this.index = index;
+    }
+
+    /**
+     * Get the join block for this phi.
+     * @return the join block of this phi
+     */
+    @Override
+    public BlockBegin block() {
+        return block;
+    }
+
+    /**
+     * Check whether this phi corresponds to a local variable.
+     * @return {@code true} if this phi refers to a local variable
+     */
+    public boolean isLocal() {
+        return index >= 0;
+    }
+
+    /**
+     * Check whether this phi corresponds to a stack location.
+     * @return {@code true} if this phi refers to a stack location
+     */
+    public boolean isOnStack() {
+        return index < 0;
+    }
+
+    /**
+     * Get the local index of this phi.
+     * @return the local index
+     */
+    public int localIndex() {
+        assert isLocal();
+        return index;
+    }
+
+    /**
+     * Get the stack index of this phi.
+     * @return the stack index of this phi
+     */
+    public int stackIndex() {
+        assert isOnStack();
+        return -(index + 1);
+    }
+
+    /**
+     * 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 inputAt(int i) {
+        FrameState state;
+        if (block.isExceptionEntry()) {
+            state = block.exceptionHandlerStates().get(i);
+        } else {
+            state = block.predecessors().get(i).end().stateAfter();
+        }
+        return inputIn(state);
+    }
+
+    /**
+     * Gets the instruction that produces the value for this phi in the specified state.
+     * @param state the state to access
+     * @return the instruction producing the value
+     */
+    public Value inputIn(FrameState state) {
+        if (isLocal()) {
+            return state.localAt(localIndex());
+        } else {
+            return state.stackAt(stackIndex());
+        }
+    }
+
+    /**
+     * 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 inputCount() {
+        if (block.isExceptionEntry()) {
+            return block.exceptionHandlerStates().size();
+        } else {
+            return block.predecessors().size();
+        }
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitPhi(this);
+    }
+
+    /**
+     * Make this phi illegal if types were not merged correctly.
+     */
+    public void makeDead() {
+        setFlag(Flag.PhiCannotSimplify);
+        setFlag(Flag.PhiDead);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("phi function");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/PointerOp.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,118 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The base class for pointer access operations.
+ *
+ * @author Doug Simon
+ */
+public abstract class PointerOp extends StateSplit {
+
+    /**
+     * The kind of value at the address accessed by the pointer operation.
+     */
+    public final CiKind dataKind;
+
+    public final int opcode;
+    protected Value pointer;
+    protected Value displacement;
+    protected Value offsetOrIndex;
+    protected final boolean isVolatile;
+    final boolean isPrefetch;
+
+    /**
+     * Creates an instruction for a pointer operation. If {@code displacement != null}, the effective of the address of the operation is
+     * computed as the pointer plus a byte displacement plus a scaled index. Otherwise, the effective address is computed as the
+     * pointer plus a byte offset.
+     *
+     * @param kind the kind of value produced by this operation
+     * @param dataKind the kind of value at the address accessed by the pointer operation
+     * @param opcode the opcode of the instruction
+     * @param pointer the value producing the pointer
+     * @param displacement the value producing the displacement. This may be {@code null}.
+     * @param offsetOrIndex the value producing the scaled-index or the byte offset depending on whether {@code displacement} is {@code null}
+     * @param stateBefore the state before
+     * @param isVolatile {@code true} if the access is volatile
+     */
+    public PointerOp(CiKind kind, CiKind dataKind, int opcode, Value pointer, Value displacement, Value offsetOrIndex, FrameState stateBefore, boolean isVolatile) {
+        super(kind.stackKind(), stateBefore);
+        this.opcode = opcode;
+        this.pointer = pointer;
+        this.dataKind = dataKind;
+        this.displacement = displacement;
+        this.offsetOrIndex = offsetOrIndex;
+        this.isVolatile = isVolatile;
+        this.isPrefetch = false;
+        if (pointer.isNonNull()) {
+            eliminateNullCheck();
+        }
+    }
+
+    public Value pointer() {
+        return pointer;
+    }
+
+    public Value index() {
+        return offsetOrIndex;
+    }
+
+    public Value offset() {
+        return offsetOrIndex;
+    }
+
+    public Value displacement() {
+        return displacement;
+    }
+
+    @Override
+    public void runtimeCheckCleared() {
+        clearState();
+    }
+
+    /**
+     * Checks whether this field access may cause a trap or an exception, which
+     * is if it either requires a null check or needs patching.
+     * @return {@code true} if this field access can cause a trap
+     */
+    @Override
+    public boolean canTrap() {
+        return needsNullCheck();
+    }
+
+    /**
+     * Iterates over the input values to this instruction.
+     * @param closure the closure to apply to each value
+     */
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        pointer = closure.apply(pointer);
+        offsetOrIndex = closure.apply(offsetOrIndex);
+        if (displacement != null) {
+            displacement = closure.apply(displacement);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/ResolveClass.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,83 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * An instruction that represents the runtime resolution of a Java class object. For example, an
+ * ldc of a class constant that is unresolved.
+ *
+ * @author Ben L. Titzer
+ * @author Thomas Wuerthinger
+ */
+public final class ResolveClass extends StateSplit {
+
+    public final RiType type;
+    public final RiType.Representation portion;
+
+    public ResolveClass(RiType type, RiType.Representation r, FrameState stateBefore) {
+        super(type.getRepresentationKind(r), stateBefore);
+        this.portion = r;
+        this.type = type;
+        setFlag(Flag.NonNull);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitResolveClass(this);
+    }
+
+    @Override
+    public boolean canTrap() {
+        return true;
+    }
+
+    @Override
+    public int valueNumber() {
+        return 0x50000000 | type.hashCode();
+    }
+
+    @Override
+    public boolean valueEqual(Instruction x) {
+        if (x instanceof ResolveClass) {
+            ResolveClass r = (ResolveClass) x;
+            return r.portion == portion && r.type.equals(type);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return super.toString() + "(type: " + type + ", portion: " + portion + ")";
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("resolve[").print(CiUtil.toJavaName(type)).print("-" + portion + "]");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/Return.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code Return} class definition.
+ *
+ * @author Ben L. Titzer
+ */
+public final class Return extends BlockEnd {
+
+    Value result;
+
+    /**
+     * Constructs a new Return instruction.
+     * @param result the instruction producing the result for this return; {@code null} if this
+     * is a void return
+     * @param isSafepoint {@code true} if this instruction is a safepoint instruction
+     */
+    public Return(Value result, boolean isSafepoint) {
+        super(result == null ? CiKind.Void : result.kind, null, isSafepoint);
+        this.result = result;
+    }
+
+    /**
+     * Gets the instruction that produces the result for the return.
+     * @return the instruction producing the result
+     */
+    public Value result() {
+        return result;
+    }
+
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        if (result != null) {
+            result = closure.apply(result);
+        }
+    }
+
+    @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);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/ShiftOp.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,54 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.cri.bytecode.*;
+
+/**
+ * The {@code ShiftOp} class represents shift operations.
+ *
+ * @author Ben L. Titzer
+ */
+public final class ShiftOp extends Op2 {
+
+    /**
+     * Creates a new shift operation.
+     * @param opcode the opcode of the shift
+     * @param x the first input value
+     * @param y the second input value
+     */
+    public ShiftOp(int opcode, Value x, Value y) {
+        super(x.kind, opcode, x, y);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitShiftOp(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(x()).print(' ').print(Bytecodes.operator(opcode)).print(' ').print(y());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/SignificantBitOp.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,94 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.util.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+/**
+ * Implements the {@link Bytecodes#LSB} and {@link Bytecodes#MSB} instructions.
+ *
+ * @author Laurent Daynes
+ */
+public class SignificantBitOp extends Instruction {
+    Value value;
+
+    /**
+     * This will be {@link Bytecodes#LSB} or {@link Bytecodes#MSB}.
+     */
+    public final int op;
+
+    /**
+     * Create a a new SignificantBitOp instance.
+     *
+     * @param value the instruction producing the value that is input to this instruction
+     * @param opcodeop either {@link Bytecodes#LSB} or {@link Bytecodes#MSB}
+     */
+    public SignificantBitOp(Value value, int opcodeop) {
+        super(CiKind.Int);
+        assert opcodeop == Bytecodes.LSB || opcodeop == Bytecodes.MSB;
+        this.value = value;
+        this.op = opcodeop;
+    }
+
+    /**
+     * Gets the instruction producing input to this instruction.
+     * @return the instruction that produces this instruction's input
+     */
+    public Value value() {
+        return value;
+    }
+
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        value = closure.apply(value);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitSignificantBit(this);
+    }
+
+    @Override
+    public int valueNumber() {
+        return Util.hash1(op, value);
+    }
+
+    @Override
+    public boolean valueEqual(Instruction i) {
+        if (i instanceof SignificantBitOp) {
+            SignificantBitOp o = (SignificantBitOp) i;
+            // FIXME: this is a conservative estimate. If x is a single-bit value
+            // (i.e., a power of 2), then the values are equal regardless of the value of the most field.
+            return value == o.value && op == o.op;
+        }
+        return false;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(Bytecodes.nameOf(op) + " [").print(this).print("] ");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/StackAllocate.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,69 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+/**
+ * Instruction implementing the semantics of {@link Bytecodes#ALLOCA}.
+ *
+ * @author Doug Simon
+ */
+public final class StackAllocate extends Instruction {
+
+    private Value size;
+
+    /**
+     * Creates a new StackAllocate instance.
+     */
+    public StackAllocate(Value size) {
+        super(CiKind.Word);
+        this.size = size;
+        setFlag(Flag.NonNull);
+        eliminateNullCheck();
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitStackAllocate(this);
+    }
+
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        size = closure.apply(size);
+    }
+
+    /**
+     * Gets the instruction that produced the size argument.
+     */
+    public Value size() {
+        return size;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("alloca(").print(size).print(")");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/StackHandle.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,71 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+/**
+ * Instruction implementing the semantics of {@link Bytecodes#STACKHANDLE}.
+ *
+ * @author Doug Simon
+ */
+public final class StackHandle extends Instruction {
+
+    /**
+     * The value that will be used to initialize the stack slot by allocated by this instruction.
+     */
+    private Value value;
+
+    /**
+     * Creates a new LoadStackAddress instance.
+     */
+    public StackHandle(Value value) {
+        super(CiKind.Word);
+        setFlag(Flag.NonNull);
+        this.value = value;
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitAllocateStackHandle(this);
+    }
+
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        value = closure.apply(value);
+    }
+
+    /**
+     * Gets the instruction that produced the size argument.
+     */
+    public Value value() {
+        return value;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("stackHandle(").print(value).print(")");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/StateSplit.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,87 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.value.*;
+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.
+ *
+ * @author Ben L. Titzer
+ */
+public abstract class StateSplit extends Instruction {
+
+    /**
+     * Sentinel denoting an explicitly cleared state.
+     */
+    private static final FrameState CLEARED_STATE = new MutableFrameState(null, -5, 0, 0);
+
+    private FrameState stateBefore;
+
+    /**
+     * Creates a new state split with the specified value type.
+     * @param kind the type of the value that this instruction produces
+     */
+    public StateSplit(CiKind kind, FrameState stateBefore) {
+        super(kind);
+        this.stateBefore = stateBefore;
+    }
+
+    /**
+     * Determines if the state for this instruction has explicitly
+     * been cleared (as opposed to never initialized). Once explicitly
+     * cleared, an instruction must not have it state (re)set.
+     */
+    public boolean isStateCleared() {
+        return stateBefore == CLEARED_STATE;
+    }
+
+    /**
+     * Clears the state for this instruction. Once explicitly
+     * cleared, an instruction must not have it state (re)set.
+     */
+    protected void clearState() {
+        stateBefore = CLEARED_STATE;
+    }
+
+    /**
+     * Records the state of this instruction before it is executed.
+     *
+     * @param stateBefore the state
+     */
+    public final void setStateBefore(FrameState stateBefore) {
+        assert this.stateBefore == null;
+        this.stateBefore = stateBefore;
+    }
+
+    /**
+     * Gets the state for this instruction.
+     * @return the state
+     */
+    @Override
+    public final FrameState stateBefore() {
+        return stateBefore == CLEARED_STATE ? null : stateBefore;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/StoreField.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code StoreField} instruction represents a write to a static or instance field.
+ *
+ * @author Ben L. Titzer
+ */
+public final class StoreField extends AccessField {
+
+    /**
+     * The value to store.
+     */
+    Value value;
+
+    /**
+     * 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 isStatic indicates if the field is static
+     * @param stateBefore the state before the field access
+     * @param isLoaded indicates if the class is loaded
+     */
+    public StoreField(Value object, RiField field, Value value, boolean isStatic, FrameState stateBefore, boolean isLoaded) {
+        super(CiKind.Void, object, field, isStatic, stateBefore, isLoaded);
+        this.value = value;
+        setFlag(Flag.LiveStore);
+        if (value.kind != CiKind.Object) {
+            setFlag(Flag.NoWriteBarrier);
+        }
+    }
+
+    /**
+     * Gets the value that is written to the field.
+     * @return the value
+     */
+    public Value value() {
+        return value;
+    }
+
+    /**
+     * Checks whether this instruction needs a write barrier.
+     * @return {@code true} if this instruction needs a write barrier
+     */
+    public boolean needsWriteBarrier() {
+        return !checkFlag(Flag.NoWriteBarrier);
+    }
+
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        super.inputValuesDo(closure);
+        value = closure.apply(value);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitStoreField(this);
+    }
+
+    @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(']');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/StoreIndexed.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,113 @@
+/*
+ * 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.sun.c1x.ir;
+
+import static com.sun.c1x.ir.Value.Flag.*;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code StoreIndexed} instruction represents a write to an array element.
+ *
+ * @author Ben L. Titzer
+ */
+public final class StoreIndexed extends AccessIndexed {
+
+    /**
+     * The value to store.
+     */
+    Value value;
+
+    /**
+     * 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 elementType the element type
+     * @param value the value to store into the array
+     * @param stateBefore the state before executing this instruction
+     */
+    public StoreIndexed(Value array, Value index, Value length, CiKind elementType, Value value, FrameState stateBefore) {
+        super(CiKind.Void, array, index, length, elementType, stateBefore);
+        this.value = value;
+        setFlag(Flag.LiveStore);
+        if (elementType != CiKind.Object) {
+            setFlag(Flag.NoWriteBarrier);
+        }
+    }
+
+    /**
+     * Gets the instruction that produces the value that is to be stored into the array.
+     * @return the value to write into the array
+     */
+    public Value value() {
+        return value;
+    }
+
+    /**
+     * Checks if this instruction needs a write barrier.
+     * @return {@code true} if this instruction needs a write barrier
+     */
+    public boolean needsWriteBarrier() {
+        return !checkFlag(Flag.NoWriteBarrier);
+    }
+
+    /**
+     * Checks if this instruction needs a store check.
+     * @return {@code true} if this instruction needs a store check
+     */
+    public boolean needsStoreCheck() {
+        return !checkFlag(Flag.NoStoreCheck);
+    }
+
+    public void eliminateStoreCheck() {
+        clearRuntimeCheck(NoStoreCheck);
+    }
+
+    /**
+     * Checks whether this instruction can cause a trap.
+     * @return {@code true} if this instruction can cause a trap
+     */
+    @Override
+    public boolean canTrap() {
+        return super.canTrap() || needsStoreCheck();
+    }
+
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        super.inputValuesDo(closure);
+        value = closure.apply(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(')');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/StorePointer.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code StorePointer} instruction represents a write of a pointer.
+ * This instruction is part of the HIR support for low-level operations, such as safepoints,
+ * stack banging, etc, and does not correspond to a Java operation.
+ *
+ * @author Ben L. Titzer
+ * @author Doug Simon
+ */
+public final class StorePointer extends PointerOp {
+
+    Value value;
+
+    /**
+     * Creates an instruction for a pointer store. If {@code displacement != null}, the effective of the address of the store is
+     * computed as the pointer plus a byte displacement plus a scaled index. Otherwise, the effective address is computed as the
+     * pointer plus a byte offset.
+     * @param dataKind the kind of value at the address accessed by the pointer operation
+     * @param pointer the value producing the pointer
+     * @param displacement the value producing the displacement. This may be {@code null}.
+     * @param offsetOrIndex the value producing the scaled-index or the byte offset depending on whether {@code displacement} is {@code null}
+     * @param value the value to write to the pointer
+     * @param stateBefore the state before
+     * @param isVolatile {@code true} if the access is volatile
+     */
+    public StorePointer(int opcode, CiKind dataKind, Value pointer, Value displacement, Value offsetOrIndex, Value value, FrameState stateBefore, boolean isVolatile) {
+        super(CiKind.Void, dataKind, opcode, pointer, displacement, offsetOrIndex, stateBefore, isVolatile);
+        this.value = value;
+        setFlag(Flag.LiveStore);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitStorePointer(this);
+    }
+
+    public Value value() {
+        return value;
+    }
+
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        super.inputValuesDo(closure);
+        value = closure.apply(value);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("*(").print(pointer);
+        if (displacement() == null) {
+            out.print(" + ").print(offset());
+        } else {
+            out.print(" + ").print(displacement()).print(" + (").print(index()).print(" * sizeOf(" + dataKind.name() + "))");
+        }
+        out.print(") := ").print(value());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/StoreRegister.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code StoreRegister} instruction represents a write of a physical register.
+ * This instruction is part of the HIR support for low-level operations, such as safepoints,
+ * stack banging, etc, and does not correspond to a Java operation.
+ *
+ * @author Ben L. Titzer
+ */
+public final class StoreRegister extends Instruction {
+
+    public final CiRegister register;
+    Value value;
+
+    /**
+     * Creates a new StoreReigster instance.
+     * @param kind the kind of value stored to the register
+     * @param register the register to store
+     * @param value the value to write
+     */
+    public StoreRegister(CiKind kind, CiRegister register, Value value) {
+        super(kind);
+        this.register = register;
+        this.value = value;
+        setFlag(Flag.LiveStore);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitStoreRegister(this);
+    }
+
+    public Value value() {
+        return value;
+    }
+
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        value = closure.apply(value);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(register.toString()).print(" := ").print(value());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/Switch.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,75 @@
+/*
+ * 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.sun.c1x.ir;
+
+import java.util.*;
+
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code Switch} class is the base of both lookup and table switches.
+ *
+ * @author Ben L. Titzer
+ */
+public abstract class Switch extends BlockEnd {
+
+    Value value;
+
+    /**
+     * 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 stateBefore the state before the switch
+     * @param isSafepoint {@code true} if this switch is a safepoint
+     */
+    public Switch(Value value, List<BlockBegin> successors, FrameState stateBefore, boolean isSafepoint) {
+        super(CiKind.Illegal, stateBefore, isSafepoint, successors);
+        this.value = value;
+    }
+
+    /**
+     * Gets the instruction that provides the input value to this switch.
+     * @return the instruction producing the input value
+     */
+    public Value value() {
+        return value;
+    }
+
+    /**
+     * Gets the number of cases that this switch covers (excluding the default case).
+     * @return the number of cases
+     */
+    public int numberOfCases() {
+        return successors.size() - 1;
+    }
+
+    /**
+     * Iterates over the inputs to this instruction.
+     * @param closure the closure to apply
+     */
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        value = closure.apply(value);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/TableSwitch.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.ir;
+
+import static com.sun.c1x.debug.InstructionPrinter.InstructionLineColumn.*;
+
+import java.util.*;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.value.*;
+
+/**
+ * The {@code TableSwitch} instruction represents a table switch.
+ *
+ * @author Ben L. Titzer
+ */
+public final class TableSwitch extends Switch {
+
+    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 stateBefore the state before the switch
+     * @param isSafepoint {@code true} if this instruction is a safepoint
+     */
+    public TableSwitch(Value value, List<BlockBegin> successors, int lowKey, FrameState stateBefore, boolean isSafepoint) {
+        super(value, successors, stateBefore, isSafepoint);
+        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 ");
+        if (isSafepoint()) {
+            out.print("(safepoint) ");
+        }
+        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, successors().get(i).blockID);
+        }
+        INSTRUCTION.advance(out);
+        out.print("default   : B").print(defaultSuccessor().blockID);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/TemplateCall.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,91 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+/**
+ * Represents a {@linkplain Bytecodes#TEMPLATE_CALL template call}.
+ *
+ * @author Doug Simon
+ */
+public final class TemplateCall extends Instruction {
+
+    /**
+     * The address to call (null implies a direct call that will be patched).
+     */
+    private Value address;
+
+    private Value receiver;
+
+    public TemplateCall(CiKind returnKind, Value address, Value receiver) {
+        super(returnKind.stackKind());
+        this.address = address;
+        this.receiver = receiver;
+        setFlag(Flag.LiveSideEffect); // ensure this instruction is not eliminated
+    }
+
+    @Override
+    public boolean canTrap() {
+        return true;
+    }
+
+    public Value address() {
+        return address;
+    }
+
+    public Value receiver() {
+        return receiver;
+    }
+
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        if (address != null) {
+            address = closure.apply(address);
+        }
+        if (receiver != null) {
+            receiver = closure.apply(receiver);
+        }
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitTemplateCall(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("template_call").print('(');
+        if (address != null) {
+            out.print(address);
+            if (receiver != null) {
+                out.print(", ").print(receiver);
+            }
+        } else if (receiver != null) {
+            out.print(receiver);
+            out.print(')');
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/Throw.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code Throw} instruction represents a throw of an exception.
+ *
+ * @author Ben L. Titzer
+ */
+public final class Throw extends BlockEnd {
+
+    Value exception;
+
+    FrameState stateBefore;
+
+    /**
+     * Creates a new Throw instruction.
+     * @param exception the instruction that generates the exception to throw
+     * @param stateAfter the state before the exception is thrown but after the exception object has been popped
+     * @param isSafepoint {@code true} if this instruction is a safepoint instruction
+     */
+    public Throw(Value exception, FrameState stateAfter, boolean isSafepoint) {
+        super(CiKind.Illegal, null, isSafepoint);
+        this.stateBefore = stateAfter;
+        this.exception = exception;
+    }
+
+    /**
+     * Gets the instruction which produces the exception to throw.
+     * @return the instruction producing the exception
+     */
+    public Value exception() {
+        return exception;
+    }
+
+    /**
+     * Returns the state before this throw would occur.
+     * @return the state before the throw
+     */
+    @Override
+    public FrameState stateBefore() {
+        return stateBefore;
+    }
+
+    /**
+     * Checks whether this instruction can trap.
+     * @return {@code true} because this instruction definitely throws an exception!
+     */
+    @Override
+    public boolean canTrap() {
+        return true;
+    }
+
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        exception = closure.apply(exception);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitThrow(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("throw ").print(exception());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/TypeCheck.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,119 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code TypeCheck} instruction is the base class of casts and instanceof tests.
+ *
+ * @author Ben L. Titzer
+ */
+public abstract class TypeCheck extends StateSplit {
+
+    final RiType targetClass;
+    public Value targetClassInstruction;
+    Value object;
+
+    /**
+     * 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 stateBefore the state before this instruction is executed
+     */
+    public TypeCheck(RiType targetClass, Value targetClassInstruction, Value object, CiKind kind, FrameState stateBefore) {
+        super(kind, stateBefore);
+        this.targetClass = targetClass;
+        this.targetClassInstruction = targetClassInstruction;
+        this.object = object;
+    }
+
+    /**
+     * Gets the instruction that loads the target class object that is used by this checkcast.
+     * @return the target class instruction
+     */
+    public Value targetClassInstruction() {
+        return targetClassInstruction;
+    }
+
+    /**
+     * 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 targetClass;
+    }
+
+    /**
+     * Gets the instruction which produces the object input.
+     * @return the instruction producing the object
+     */
+    public Value object() {
+        return object;
+    }
+
+    /**
+     * Checks whether the target class of this instruction is loaded.
+     * @return {@code true} if the target class is loaded
+     */
+    public boolean isLoaded() {
+        return targetClass != null;
+    }
+
+    /**
+     * Checks whether this instruction can trap.
+     * @return {@code true}, conservatively assuming the cast may fail
+     */
+    @Override
+    public boolean canTrap() {
+        return true;
+    }
+
+    /**
+     * Iterates over the input values to this instruction.
+     * @param closure the closure to apply
+     */
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        object = closure.apply(object);
+        targetClassInstruction = closure.apply(targetClassInstruction);
+    }
+
+    /**
+     * Sets this type check operation to be a direct compare.
+     */
+    public void setDirectCompare() {
+        setFlag(Flag.DirectCompare);
+    }
+
+    /**
+     * Checks where this comparison is a direct compare, because the class compared to is a leaf class.
+     * @return {@code true} if this typecheck is a direct compare
+     */
+    public boolean isDirectCompare() {
+        return checkFlag(Flag.DirectCompare);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/TypeEqualityCheck.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,71 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+
+/**
+ * Checks the types of the two input values and deoptimizes if the condition does not hold.
+ *
+ * @author Thomas Wuerthinger
+ *
+ */
+public final class TypeEqualityCheck extends Guard {
+
+    Value left;
+    Value right;
+
+    public TypeEqualityCheck(Value left, Value right, FrameState stateBefore, Condition condition) {
+        super(condition, stateBefore);
+        this.left = left;
+        this.right = right;
+        assert left.kind == CiKind.Object;
+        assert right.kind == CiKind.Object;
+    }
+
+    public Value left() {
+        return left;
+    }
+
+    public Value right() {
+        return right;
+    }
+
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        left = closure.apply(left);
+        right = closure.apply(right);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitTypeEqualityCheck(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("typeEqualityCheck ").print(left).print(" ").print(right);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/UnsafeCast.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,117 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code UnsafeCast} instruction represents a {@link Bytecodes#UNSAFE_CAST}.
+ *
+ * @author Doug Simon
+ */
+public final class UnsafeCast extends Instruction {
+
+    public final RiType toType;
+
+    /**
+     * The instruction that produced the value being unsafe cast.
+     */
+    private Value value;
+
+    /**
+     * Denotes if this is a redundant cast at the machine level. That is the source
+     * and the destination kind are implemented by the same machine kind.
+     */
+    public final boolean redundant;
+
+    /**
+     * Creates a new UnsafeCast instruction.
+     *
+     * @param toType the the being cast to
+     * @param value the value being cast
+     */
+    public UnsafeCast(RiType toType, Value value, boolean redundant) {
+        super(toType.kind().stackKind());
+        this.toType = toType;
+        this.value = value;
+        this.redundant = redundant;
+    }
+
+    /**
+     * Gets the first non-redundant value derived from this value. If this
+     * value is not {@linkplain #redundant}, then it is returned. Otherwise,
+     * the first value found by following {@link #value()} that is not an
+     * unsafe cast or is not redundant is returned.
+     */
+    public Value nonRedundantReplacement() {
+        if (!redundant) {
+            return this;
+        }
+        if (!(value instanceof UnsafeCast)) {
+            return value;
+        }
+        return ((UnsafeCast) value).nonRedundantReplacement();
+    }
+
+    /**
+     * Gets the instruction that produced the value being unsafe cast.
+     */
+    public Value value() {
+        return value;
+    }
+
+    @Override
+    public RiType declaredType() {
+        return toType;
+    }
+
+    @Override
+    public RiType exactType() {
+        return declaredType().exactType();
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitUnsafeCast(this);
+    }
+
+    /**
+     * Iterates over the input values to this instruction.
+     * @param closure the closure to apply
+     */
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        value = closure.apply(value);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("unsafe_cast(").
+        print(value).
+        print(") ").
+        print(CiUtil.toJavaName(toType));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/UnsafeGetObject.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,55 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code UnsafeGetObject} instruction represents an unsafe read.
+ *
+ * @author Ben L. Titzer
+ */
+public final class UnsafeGetObject extends UnsafeObjectOp {
+
+    /**
+     * Constructs a new UnsafeGetObject operation.
+     * @param opKind the kind of the operation
+     * @param object the instruction generating the object
+     * @param offset the instruction generating the offset
+     * @param isVolatile {@code true} if this operation is volatile
+     */
+    public UnsafeGetObject(CiKind opKind, Value object, Value offset, boolean isVolatile) {
+        super(opKind, object, offset, false, isVolatile);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitUnsafeGetObject(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("UnsafeGetObject.(").print(object()).print(", ").print(offset()).print(')');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/UnsafeGetRaw.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,83 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code UnsafeGetRaw} instruction represents an unsafe access of raw memory where
+ * the type is not an object reference.
+ *
+ * @author Ben L. Titzer
+ */
+public final class UnsafeGetRaw extends UnsafeRawOp {
+
+    final boolean mayBeUnaligned;
+
+    /**
+     * Constructs a new UnsafeGetRaw instruction.
+     * @param opKind the kind of the operation
+     * @param addr the instruction generating the base address
+     * @param mayBeUnaligned {@code true} if this operation may be unaligned
+     */
+    public UnsafeGetRaw(CiKind opKind, Value addr, boolean mayBeUnaligned) {
+        super(opKind, addr, false);
+        this.mayBeUnaligned = mayBeUnaligned;
+    }
+
+    /**
+     * Constructs a new UnsafeGetRaw instruction.
+     * @param opKind the kind of the operation
+     * @param addr the instruction generating the base address
+     * @param index the instruction generating the index
+     * @param log2scale the log base 2 of the scaling factor
+     * @param mayBeUnaligned {@code true} if this operation may be unaligned
+     */
+    public UnsafeGetRaw(CiKind opKind, Value addr, Value index, int log2scale, boolean mayBeUnaligned) {
+        super(opKind, addr, index, log2scale, false);
+        this.mayBeUnaligned = mayBeUnaligned;
+    }
+
+    /**
+     * Checks whether this operation may be unaligned.
+     * @return {@code true} if this operation may be unaligned
+     */
+    public boolean mayBeUnaligned() {
+        return mayBeUnaligned;
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitUnsafeGetRaw(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("UnsafeGetRaw.(base ").print(base());
+        if (hasIndex()) {
+            out.print(", index ").print(index()).print(", log2_scale ").print(log2Scale());
+        }
+        out.print(')');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/UnsafeObjectOp.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,87 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code UnsafeObjectOp} class is the base of all unsafe object instructions.
+ *
+ * @author Ben L. Titzer
+ */
+public abstract class UnsafeObjectOp extends UnsafeOp {
+
+    Value object;
+    Value offset;
+    final boolean isVolatile;
+
+    /**
+     * Creates a new UnsafeObjectOp instruction.
+     * @param opKind the kind of the operation
+     * @param object the instruction generating the object
+     * @param offset the instruction generating the index
+     * @param isStore {@code true} if this is a store operation
+     * @param isVolatile {@code true} if the operation is volatile
+     */
+    public UnsafeObjectOp(CiKind opKind, Value object, Value offset, boolean isStore, boolean isVolatile) {
+        super(opKind, isStore);
+        this.object = object;
+        this.offset = offset;
+        this.isVolatile = isVolatile;
+    }
+
+    /**
+     * Gets the instruction that generates the object.
+     * @return the instruction that produces the object
+     */
+    public Value object() {
+        return object;
+    }
+
+    /**
+     * Gets the instruction that generates the offset.
+     * @return the instruction generating the offset
+     */
+    public Value offset() {
+        return offset;
+    }
+
+    /**
+     * Checks whether this is a volatile operation.
+     * @return {@code true} if this operation is volatile
+     */
+    public boolean isVolatile() {
+        return isVolatile;
+    }
+
+    /**
+     * Iterates over the input values of this instruction.
+     * @param closure the closure to apply
+     */
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        super.inputValuesDo(closure);
+        object = closure.apply(object);
+        offset = closure.apply(offset);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/UnsafeOp.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,45 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code UnsafeOp} class is the base of all unsafe operations.
+ *
+ * @author Ben L. Titzer
+ */
+public abstract class UnsafeOp extends Instruction {
+    public final CiKind unsafeOpKind;
+
+    /**
+     * Creates a new UnsafeOp instruction.
+     * @param unsafeOpKind the kind of the operation
+     * @param isStore {@code true} if this is a store operation
+     */
+    public UnsafeOp(CiKind unsafeOpKind, boolean isStore) {
+        super(isStore ? CiKind.Void : unsafeOpKind.stackKind());
+        this.unsafeOpKind = unsafeOpKind;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/UnsafePrefetch.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,42 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code UnsafePrefetch} class is the base of prefetch reads and prefetch writes.
+ *
+ * @author Ben L. Titzer
+ */
+public abstract class UnsafePrefetch extends UnsafeObjectOp {
+
+    /**
+     * Creates a new UnsafePrefetch instruction.
+     * @param object the instruction generating the object
+     * @param offset the instruction generating the offset
+     */
+    public UnsafePrefetch(Value object, Value offset) {
+        super(CiKind.Void, object, offset, false, false);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/UnsafePrefetchRead.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,52 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+
+/**
+ * The {@code UnsafePrefetchRead} instruction represents a prefetch operation on an object field.
+ *
+ * @author Ben L. Titzer
+ */
+public final class UnsafePrefetchRead extends UnsafePrefetch {
+
+    /**
+     * Creates a new UnsafePrefetchRead instruction.
+     * @param object the instruction generating the object
+     * @param offset the instruction generating the offset
+     */
+    public UnsafePrefetchRead(Value object, Value offset) {
+        super(object, offset);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitUnsafePrefetchRead(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("UnsafePrefetchRead.(").print(object()).print(", ").print(offset()).print(')');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/UnsafePrefetchWrite.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,52 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+
+/**
+ * The {@code UnsafePrefetchWrite} instruction represents a prefetch write.
+ *
+ * @author Ben L. Titzer
+ */
+public final class UnsafePrefetchWrite extends UnsafePrefetch {
+
+    /**
+     * Creates a new UnsafePrefetchWrite instruction.
+     * @param object the instruction generating the object
+     * @param offset the instruction generating the offset
+     */
+    public UnsafePrefetchWrite(Value object, Value offset) {
+        super(object, offset);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitUnsafePrefetchWrite(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("UnsafePrefetchWrite.(").print(object()).print(", ").print(offset()).print(')');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/UnsafePutObject.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,74 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code UnsafePutObject} instruction represents a unsafe write operation.
+ *
+ * @author Ben L. Titzer
+ */
+public final class UnsafePutObject extends UnsafeObjectOp {
+
+    Value value;
+
+    /**
+     * Creates a new UnsafePutObject instruction.
+     * @param opKind the kind of the operation
+     * @param object the instruction generating the object
+     * @param offset the instruction generating the offset
+     * @param value the instruction generating the value
+     * @param isVolatile {@code true} if the operation is volatile
+     */
+    public UnsafePutObject(CiKind opKind, Value object, Value offset, Value value, boolean isVolatile) {
+        super(opKind, object, offset, true, isVolatile);
+        this.value = value;
+    }
+
+    /**
+     * Gets the instruction that generates the value to store.
+     * @return the instruction generating the value
+     */
+    public Value value() {
+        return value;
+    }
+
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        super.inputValuesDo(closure);
+        value = closure.apply(value);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitUnsafePutObject(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("UnsafePutObject.(").print(object()).print(", ").print(offset() +
+        ", value ").print(value()).print(')');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/UnsafePutRaw.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,79 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code UnsafePutRaw} instruction represents an unsafe store operation.
+ *
+ * @author Ben L. Titzer
+ */
+public final class UnsafePutRaw extends UnsafeRawOp {
+
+    Value value;
+
+    /**
+     * Constructs a new UnsafeGetRaw instruction.
+     * @param opKind the kind of the operation
+     * @param addr the instruction generating the base address
+     * @param value the instruction generating the value to store
+     */
+    public UnsafePutRaw(CiKind opKind, Value addr, Value value) {
+        super(opKind, addr, false);
+        this.value = value;
+    }
+
+    /**
+     * Gets the instruction generating the value that will be stored.
+     * @return the instruction generating the value
+     */
+    public Value value() {
+        return value;
+    }
+
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        super.inputValuesDo(closure);
+        value = closure.apply(value);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitUnsafePutRaw(this);
+    }
+
+    public int log2scale() {
+        return log2Scale;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("UnsafePutRaw.(base ").print(base());
+        if (hasIndex()) {
+            out.print(", index ").print(index()).print(", log2_scale ").print(log2Scale());
+        }
+        out.print(", value ").print(value()).print(')');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/UnsafeRawOp.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,133 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code UnsafeRawOp} class is the base class of all unsafe raw operations.
+ *
+ * @author Ben L. Titzer
+ */
+public abstract class UnsafeRawOp extends UnsafeOp {
+
+    Value base;
+    Value index;
+    int log2Scale;
+
+    /**
+     * Creates a new UnsafeRawOp instruction.
+     * @param opKind the kind of the operation
+     * @param addr the instruction generating the base address (a long)
+     * @param isStore {@code true} if this operation is a store
+     */
+    public UnsafeRawOp(CiKind opKind, Value addr, boolean isStore) {
+        super(opKind, isStore);
+        assert addr == null || addr.kind == CiKind.Long;
+        base = addr;
+    }
+
+    /**
+     * Creates a new UnsafeRawOp instruction.
+     * @param opKind the kind of the operation
+     * @param addr the instruction generating the base address (a long)
+     * @param index the instruction generating the index
+     * @param log2scale the log base 2 of the scaling factor
+     * @param isStore {@code true} if this operation is a store
+     */
+    public UnsafeRawOp(CiKind opKind, Value addr, Value index, int log2scale, boolean isStore) {
+        this(opKind, addr, isStore);
+        this.base = addr;
+        this.index = index;
+        this.log2Scale = log2scale;
+    }
+
+    /**
+     * Gets the instruction generating the base address for this operation.
+     * @return the instruction generating the base
+     */
+    public Value base() {
+        return base;
+    }
+
+    /**
+     * Gets the instruction generating the index for this operation.
+     * @return the instruction generating the index
+     */
+    public Value index() {
+        return index;
+    }
+
+    /**
+     * Checks whether this instruction has an index.
+     * @return {@code true} if this instruction has an index
+     */
+    public boolean hasIndex() {
+        return index != null;
+    }
+
+    /**
+     * Gets the log base 2 of the scaling factor for the index of this instruction.
+     * @return the log base 2 of the scaling factor
+     */
+    public int log2Scale() {
+        return log2Scale;
+    }
+
+    /**
+     * Sets the instruction that generates the base address for this instruction.
+     * @param base the instruction generating the base address
+     */
+    public void setBase(Value base) {
+        this.base = base;
+    }
+
+    /**
+     * Sets the instruction generating the base address for this instruction.
+     * @param index the instruction generating the index
+     */
+    public void setIndex(Value index) {
+        this.index = index;
+    }
+
+    /**
+     * Sets the scaling factor for the index of this instruction.
+     * @param log2scale the log base 2 of the scaling factor for this instruction
+     */
+    public void setLog2Scale(int log2scale) {
+        this.log2Scale = log2scale;
+    }
+
+    /**
+     * Iterates over the input values to this instruction.
+     * @param closure the closure to apply
+     */
+    @Override
+    public void inputValuesDo(ValueClosure closure) {
+        super.inputValuesDo(closure);
+        base = closure.apply(base);
+        if (index != null) {
+            index = closure.apply(index);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/UnsignedCompareOp.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,70 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.sun.c1x.debug.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.bytecode.Bytecodes.UnsignedComparisons;
+import com.sun.cri.ci.*;
+
+/**
+ * Unsigned comparisons.
+ *
+ * @author Mick Jordan
+ * @see UnsignedComparisons
+ */
+public final class UnsignedCompareOp extends Op2 {
+
+    /**
+     * One of the constants defined in {@link UnsignedComparisons} denoting the type of this comparison.
+     */
+    public final int op;
+
+    /**
+     * Creates a new compare operation.
+     *
+     * @param opcode the bytecode opcode
+     * @param op the comparison type
+     * @param x the first input
+     * @param y the second input
+     */
+    public UnsignedCompareOp(int opcode, int op, Value x, Value y) {
+        super(CiKind.Int, opcode, x, y);
+        assert opcode == Bytecodes.UWCMP || opcode == Bytecodes.UCMP;
+        this.op = op;
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitUnsignedCompareOp(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(x()).
+        print(' ').
+        print(Bytecodes.operator(opcode)).
+        print(' ').
+        print(y());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/Value.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,407 @@
+/*
+ * 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.sun.c1x.ir;
+
+import static com.sun.c1x.ir.Value.Flag.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.debug.*;
+import com.sun.c1x.opt.*;
+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.
+ *
+ * @author Ben L. Titzer
+ */
+public abstract class Value {
+    /**
+     * An enumeration of flags on values.
+     */
+    public enum Flag {
+        NonNull,            // this value is non-null
+
+        NoNullCheck,        // does not require null check
+        NoStoreCheck,       // does not require store check
+        NoBoundsCheck,      // does not require bounds check
+        NoZeroCheck,        // divide or modulus cannot cause exception
+
+        NoReadBarrier,      // does not require read barrier
+        NoWriteBarrier,     // does not require write barrier
+        NoDivSpecialCase,   // divide or modulus cannot be special case of MIN_INT / -1
+        DirectCompare,
+        IsLoaded,           // field or method is resolved and class is loaded and initialized
+        IsStatic,           // field or method access is static
+        IsSafepoint,        // branch is backward (safepoint)
+        IsStrictFP,
+        PreservesState,     // intrinsic preserves state
+        UnorderedIsTrue,
+        NeedsPatching,
+        LiveValue,          // live because value is used
+        LiveDeopt,          // live for deoptimization
+        LiveControl,        // live for control dependencies
+        LiveSideEffect,     // live for possible side-effects only
+        LiveStore,          // instruction is a store
+        PhiDead,            // phi is illegal because local is dead
+        PhiCannotSimplify,  // phi cannot be simplified
+        PhiVisited,         // phi has been visited during simplification
+
+        ResultIsUnique;     // the result of this instruction is guaranteed to be unique (e.g. a new object)
+
+        public final int mask = 1 << ordinal();
+    }
+
+    private static final int LIVE_FLAGS = Flag.LiveValue.mask |
+                                          Flag.LiveDeopt.mask |
+                                          Flag.LiveControl.mask |
+                                          Flag.LiveSideEffect.mask;
+    /**
+     * 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;
+
+    /**
+     * Unique identifier for this value. This field's value is lazily initialized by {@link #id()}.
+     */
+    private int id;
+
+    /**
+     * A mask of {@linkplain Flag flags} denoting extra properties of this value.
+     */
+    private int flags;
+
+    protected CiValue operand = CiValue.IllegalValue;
+
+    /**
+     * A cache for analysis information. Every optimization must reset this field to {@code null} once it has completed.
+     */
+    public Object optInfo;
+
+    /**
+     * Used by {@link InstructionSubstituter}.
+     */
+    public Value subst;
+
+    public abstract BlockBegin block();
+
+    /**
+     * Creates a new value with the specified kind.
+     * @param kind the type of this value
+     */
+    public Value(CiKind kind) {
+        assert kind == kind.stackKind() : kind + " != " + kind.stackKind();
+        this.kind = kind;
+    }
+
+    /**
+     * Checks whether this instruction is live (i.e. code should be generated for it).
+     * This is computed in a dedicated pass by {@link LivenessMarker}.
+     * An instruction is live because its value is needed by another live instruction,
+     * because its value is needed for deoptimization, or the program is control dependent
+     * upon it.
+     * @return {@code true} if this instruction should be considered live
+     */
+    public final boolean isLive() {
+        return C1XOptions.PinAllInstructions || (flags & LIVE_FLAGS) != 0;
+    }
+
+    /**
+     * Clears all liveness flags.
+     */
+    public final void clearLive() {
+        flags = flags & ~LIVE_FLAGS;
+    }
+
+    /**
+     * Gets the instruction that should be substituted for this one. Note that this
+     * method is recursive; if the substituted instruction has a substitution, then
+     * the final substituted instruction will be returned. If there is no substitution
+     * for this instruction, {@code this} will be returned.
+     * @return the substitution for this instruction
+     */
+    public final Value subst() {
+        if (subst == null) {
+            return this;
+        }
+        return subst.subst();
+    }
+
+    /**
+     * Checks whether this instruction has a substitute.
+     * @return {@code true} if this instruction has a substitution.
+     */
+    public final boolean hasSubst() {
+        return subst != null;
+    }
+
+    /**
+     * Eliminates a given runtime check for this instruction.
+     *
+     * @param flag the flag representing the (elimination of the) runtime check
+     */
+    public final void clearRuntimeCheck(Flag flag) {
+        if (!checkFlag(flag)) {
+            setFlag(flag);
+            runtimeCheckCleared();
+            if (flag == NoNullCheck) {
+                C1XMetrics.NullCheckEliminations++;
+            } else if (flag == NoBoundsCheck) {
+                C1XMetrics.BoundsChecksElminations++;
+            } else if (flag == NoStoreCheck) {
+                C1XMetrics.StoreCheckEliminations++;
+            } else if (flag != NoZeroCheck) {
+                throw new InternalError("Unknown runtime check: " + flag);
+            }
+        }
+    }
+
+
+    /**
+     * Clear any internal state related to null checks, because a null check
+     * for this instruction is redundant. The state cleared may depend
+     * on the type of this instruction
+     */
+    public final void eliminateNullCheck() {
+        clearRuntimeCheck(NoNullCheck);
+    }
+
+    /**
+     * Notifies this instruction that a runtime check has been
+     * eliminated or made redundant.
+     */
+    protected void runtimeCheckCleared() {
+    }
+
+    /**
+     * Check whether this instruction has the specified flag set.
+     * @param flag the flag to test
+     * @return {@code true} if this instruction has the flag
+     */
+    public final boolean checkFlag(Flag flag) {
+        return (flags & flag.mask) != 0;
+    }
+
+    /**
+     * Set a flag on this instruction.
+     * @param flag the flag to set
+     */
+    public final void setFlag(Flag flag) {
+        flags |= flag.mask;
+    }
+
+    /**
+     * Clear a flag on this instruction.
+     * @param flag the flag to set
+     */
+    public final void clearFlag(Flag flag) {
+        flags &= ~flag.mask;
+    }
+
+    /**
+     * Set or clear a flag on this instruction.
+     * @param flag the flag to set
+     * @param val if {@code true}, set the flag, otherwise clear it
+     */
+    public final void setFlag(Flag flag, boolean val) {
+        if (val) {
+            setFlag(flag);
+        } else {
+            clearFlag(flag);
+        }
+    }
+
+    /**
+     * Initialize a flag on this instruction. Assumes the flag is not initially set,
+     * e.g. in the constructor of an instruction.
+     * @param flag the flag to set
+     * @param val if {@code true}, set the flag, otherwise do nothing
+     */
+    public final void initFlag(Flag flag, boolean val) {
+        if (val) {
+            setFlag(flag);
+        }
+    }
+
+    /**
+     * Checks whether this instruction produces a value which is guaranteed to be non-null.
+     * @return {@code true} if this instruction's value is not null
+     */
+    public final boolean isNonNull() {
+        return checkFlag(Flag.NonNull);
+    }
+
+    /**
+     * Checks whether this instruction needs a null check.
+     * @return {@code true} if this instruction needs a null check
+     */
+    public final boolean needsNullCheck() {
+        return !checkFlag(Flag.NoNullCheck);
+    }
+
+    /**
+     * 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();
+    }
+
+    /**
+     * Checks whether this instruction "is illegal"--i.e. it represents a dead
+     * phi or an instruction which does not produce a value.
+     * @return {@code true} if this instruction is illegal as an input value to another instruction
+     */
+    public final boolean isIllegal() {
+        return checkFlag(Flag.PhiDead);
+    }
+
+    /**
+     * 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;
+        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
+    }
+
+    /**
+     * Apply the specified closure to all the input values of this instruction.
+     * @param closure the closure to apply
+     */
+    public void inputValuesDo(ValueClosure closure) {
+        // default: do nothing.
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append(getClass().getSimpleName());
+        builder.append(" #");
+        builder.append(id());
+        if (this instanceof Instruction) {
+            builder.append(" @ ");
+            builder.append(((Instruction) this).bci());
+        }
+        builder.append(" [").append(flagsToString()).append("]");
+        return builder.toString();
+    }
+
+    public String flagsToString() {
+        StringBuilder sb = new StringBuilder();
+        for (Flag f : Flag.values()) {
+            if (checkFlag(f)) {
+                if (sb.length() != 0) {
+                    sb.append(' ');
+                }
+                sb.append(f.name());
+            }
+        }
+        return sb.toString();
+    }
+
+    public final boolean isDeadPhi() {
+        return checkFlag(Flag.PhiDead);
+    }
+
+    /**
+     * This method supports the visitor pattern by accepting a visitor and calling the
+     * appropriate {@code visit()} method.
+     *
+     * @param v the visitor to accept
+     */
+    public abstract void accept(ValueVisitor v);
+
+    public abstract void print(LogStream out);
+
+    /**
+     * This method returns a unique identification number for this value. The number returned is unique
+     * only to the compilation that produced this node and is computed lazily by using the current compilation
+     * for the current thread. Thus the first access is a hash lookup using {@link java.lang.ThreadLocal} and
+     * should not be considered fast. Because of the potentially slow first access, use of this ID should be
+     * restricted to debugging output.
+     * @return a unique ID for this value
+     */
+    public int id() {
+        if (id == 0) {
+            C1XMetrics.UniqueValueIdsAssigned++;
+            id = C1XCompilation.compilation().nextID();
+        }
+        return id;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/ValueClosure.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,33 @@
+/*
+ * 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.sun.c1x.ir;
+
+/**
+ * The {@code ValueClosure} interface represents a first-class
+ * function that can be applied to a value.
+ *
+ * @author Ben L. Titzer
+ */
+public interface ValueClosure {
+    Value apply(Value i);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/ValueVisitor.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,99 @@
+/*
+ * 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.sun.c1x.ir;
+
+/**
+ * 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.
+ *
+ * @author Ben L. Titzer
+ */
+public abstract class ValueVisitor {
+    // Checkstyle: stop
+    public abstract void visitArithmeticOp(ArithmeticOp i);
+    public abstract void visitArrayCopy(ArrayCopy arrayCopy);
+    public abstract void visitArrayLength(ArrayLength i);
+    public abstract void visitBase(Base i);
+    public abstract void visitBoundsCheck(BoundsCheck boundsCheck);
+    public abstract void visitBlockBegin(BlockBegin i);
+    public abstract void visitBreakpointTrap(BreakpointTrap i);
+    public abstract void visitCheckCast(CheckCast i);
+    public abstract void visitCompareOp(CompareOp i);
+    public abstract void visitCompareAndSwap(CompareAndSwap i);
+    public abstract void visitConstant(Constant i);
+    public abstract void visitConvert(Convert i);
+    public abstract void visitExceptionObject(ExceptionObject i);
+    public abstract void visitGoto(Goto i);
+    public abstract void visitIf(If i);
+    public abstract void visitIfOp(IfOp i);
+    public abstract void visitInstanceOf(InstanceOf i);
+    public abstract void visitIntrinsic(Intrinsic i);
+    public abstract void visitInvoke(Invoke i);
+    public abstract void visitLoadField(LoadField i);
+    public abstract void visitLoadIndexed(LoadIndexed i);
+    public abstract void visitIncrementRegister(IncrementRegister i);
+    public abstract void visitInfopoint(Infopoint i);
+    public abstract void visitLoadPointer(LoadPointer i);
+    public abstract void visitAllocateStackHandle(StackHandle i);
+    public abstract void visitLoadRegister(LoadRegister i);
+    public abstract void visitLocal(Local i);
+    public abstract void visitLogicOp(LogicOp i);
+    public abstract void visitLookupSwitch(LookupSwitch i);
+    public abstract void visitMemoryBarrier(MemoryBarrier memoryBarrier);
+    public abstract void visitMonitorAddress(MonitorAddress monitorAddress);
+    public abstract void visitMonitorEnter(MonitorEnter i);
+    public abstract void visitMonitorExit(MonitorExit i);
+    public abstract void visitNativeCall(NativeCall i);
+    public abstract void visitNegateOp(NegateOp i);
+    public abstract void visitNewInstance(NewInstance i);
+    public abstract void visitNewMultiArray(NewMultiArray i);
+    public abstract void visitNewObjectArray(NewObjectArray i);
+    public abstract void visitNewObjectArrayClone(NewObjectArrayClone newObjectArrayClone);
+    public abstract void visitNewTypeArray(NewTypeArray i);
+    public abstract void visitNullCheck(NullCheck i);
+    public abstract void visitOsrEntry(OsrEntry i);
+    public abstract void visitPause(Pause i);
+    public abstract void visitPhi(Phi i);
+    public abstract void visitResolveClass(ResolveClass i);
+    public abstract void visitReturn(Return i);
+    public abstract void visitShiftOp(ShiftOp i);
+    public abstract void visitSignificantBit(SignificantBitOp i);
+    public abstract void visitStackAllocate(StackAllocate i);
+    public abstract void visitStoreField(StoreField i);
+    public abstract void visitStoreIndexed(StoreIndexed i);
+    public abstract void visitStorePointer(StorePointer i);
+    public abstract void visitStoreRegister(StoreRegister i);
+    public abstract void visitTableSwitch(TableSwitch i);
+    public abstract void visitTemplateCall(TemplateCall templateCall);
+    public abstract void visitThrow(Throw i);
+    public abstract void visitTypeEqualityCheck(TypeEqualityCheck typeEqualityCheck);
+    public abstract void visitUnsafeCast(UnsafeCast i);
+    public abstract void visitUnsafeGetObject(UnsafeGetObject i);
+    public abstract void visitUnsafeGetRaw(UnsafeGetRaw i);
+    public abstract void visitUnsafePrefetchRead(UnsafePrefetchRead i);
+    public abstract void visitUnsafePrefetchWrite(UnsafePrefetchWrite i);
+    public abstract void visitUnsafePutObject(UnsafePutObject i);
+    public abstract void visitUnsafePutRaw(UnsafePutRaw i);
+    public abstract void visitUnsignedCompareOp(UnsignedCompareOp i);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/ir/package-info.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,34 @@
+/*
+ * 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
+ *
+ *         Classes that define the (High-level) Intermediate Representation (HIR) if the C1X compiler.
+ *
+ *         HIR instances are created by processing Java bytecodes and are Directed Acyclic Graphs (DAGs). All nodes in
+ *         an HIR graph are concrete subclasses of the abstract class {@link Value}. This indicates a property of HIR,
+ *         namely that everything is a value, including instructions. This allows an operand for an instruction node to
+ *         refer directly to the node that generated the value, which might, for example, be another instruction.
+ */
+package com.sun.c1x.ir;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/lir/FrameMap.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,394 @@
+/*
+ * 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.sun.c1x.lir;
+
+import static com.sun.cri.ci.CiCallingConvention.Type.*;
+import static com.sun.cri.ci.CiKind.*;
+import static java.lang.reflect.Modifier.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.globalstub.*;
+import com.sun.c1x.util.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ci.CiCallingConvention.Type;
+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}.
+ *
+ * @author Thomas Wuerthinger
+ * @author Ben L. Titzer
+ * @author Doug Simon
+ */
+public final class FrameMap {
+
+    private final C1XCompilation 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(C1XCompilation 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(Util.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);
+        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.getCalleeSaveArea().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;
+            return new CiAddress(slot.kind, CiRegister.CallerFrame.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";
+        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.getCalleeSaveArea().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/Compiler/src/com/sun/c1x/lir/LIRAssembler.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,544 @@
+/*
+ * 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.sun.c1x.lir;
+
+import java.util.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.asm.*;
+import com.sun.c1x.debug.*;
+import com.sun.c1x.gen.*;
+import com.sun.c1x.ir.*;
+import com.sun.c1x.lir.FrameMap.StackBlock;
+import com.sun.c1x.util.*;
+import com.sun.c1x.value.*;
+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.
+ *
+ * @author Marcelo Cintra
+ * @author Thomas Wuerthinger
+ * @author Ben L. Titzer
+ */
+public abstract class LIRAssembler {
+
+    public final C1XCompilation compilation;
+    public final AbstractAssembler asm;
+    public final FrameMap frameMap;
+    public int registerRestoreEpilogueOffset = -1;
+
+    protected final List<SlowPath> xirSlowPath;
+    protected final List<BlockBegin> branchTargetBlocks;
+
+    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(C1XCompilation compilation) {
+        this.compilation = compilation;
+        this.asm = compilation.masm();
+        this.frameMap = compilation.frameMap();
+        this.branchTargetBlocks = new ArrayList<BlockBegin>();
+        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 emitExceptionEntries() {
+        if (asm.exceptionInfoList == null) {
+            return;
+        }
+        for (ExceptionInfo ilist : asm.exceptionInfoList) {
+            List<ExceptionHandler> handlers = ilist.exceptionHandlers;
+
+            for (ExceptionHandler handler : handlers) {
+                assert handler.lirOpId() != -1 : "handler not processed by LinearScan";
+                assert handler.entryCode() == null || handler.entryCode().instructionsList().get(handler.entryCode().instructionsList().size() - 1).code == LIROpcode.Branch : "last operation must be branch";
+
+                if (handler.entryCodeOffset() == -1) {
+                    // entry code not emitted yet
+                    if (handler.entryCode() != null && handler.entryCode().instructionsList().size() > 1) {
+                        handler.setEntryCodeOffset(codePos());
+                        if (C1XOptions.CommentedAssembly) {
+                            asm.blockComment("Exception adapter block");
+                        }
+                        emitLirList(handler.entryCode());
+                    } else {
+                        handler.setEntryCodeOffset(handler.entryBlock().exceptionHandlerPco());
+                    }
+
+                    assert handler.entryCodeOffset() != -1 : "must be set now";
+                }
+            }
+        }
+    }
+
+    public void emitCode(List<BlockBegin> hir) {
+        if (C1XOptions.PrintLIR && !TTY.isSuppressed()) {
+            LIRList.printLIR(hir);
+        }
+
+        for (BlockBegin b : hir) {
+            emitBlock(b);
+        }
+
+        assert checkNoUnboundLabels();
+    }
+
+    void emitBlock(BlockBegin block) {
+        if (block.checkBlockFlag(BlockBegin.BlockFlag.BackwardBranchTarget)) {
+            emitAlignment();
+        }
+
+        // if this block is the start of an exception handler, record the
+        // PC offset of the first instruction for later construction of
+        // the ExceptionHandlerTable
+        if (block.checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry)) {
+            block.setExceptionHandlerPco(codePos());
+        }
+
+        if (C1XOptions.PrintLIRWithAssembly) {
+            block.printWithoutPhis(TTY.out());
+        }
+
+        assert block.lir() != null : "must have LIR";
+        if (C1XOptions.CommentedAssembly) {
+            String st = String.format(" block B%d [%d, %d]", block.blockID, block.bci(), block.end().bci());
+            asm.blockComment(st);
+        }
+
+        emitLirList(block.lir());
+    }
+
+    void emitLirList(LIRList list) {
+        doPeephole(list);
+
+        for (LIRInstruction op : list.instructionsList()) {
+            if (C1XOptions.CommentedAssembly) {
+                // Only print out branches
+                if (op.code == LIROpcode.Branch) {
+                    asm.blockComment(op.toStringWithIdPrefix());
+                }
+            }
+            if (C1XOptions.PrintLIRWithAssembly && !TTY.isSuppressed()) {
+                // print out the LIR operation followed by the resulting assembly
+                TTY.println(op.toStringWithIdPrefix());
+                TTY.println();
+            }
+
+            op.emitCode(this);
+
+            if (C1XOptions.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, C1XOptions.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;
+    }
+
+    static FrameState stateBefore(Value ins) {
+        if (ins instanceof Instruction) {
+            return ((Instruction) ins).stateBefore();
+        }
+        return null;
+    }
+
+    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, asm.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, asm.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:
+                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:
+                assert op.operand().isRegister();
+                if (C1XOptions.NullCheckUniquePc) {
+                    asm.nop();
+                }
+                asm.recordImplicitException(codePos(), op.info);
+                asm.nullCheck(op.operand().asRegister());
+                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 OsrEntry:
+                emitOsrEntry();
+                break;
+            case Here:
+                emitHere(op.result(), op.info, false);
+                break;
+            case Info:
+                emitHere(op.result(), op.info, true);
+                break;
+            case Pause:
+                emitPause();
+                break;
+            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;
+
+            case Throw:
+            case Unwind:
+                emitThrow(op.operand1(), op.operand2(), op.info, op.code == LIROpcode.Unwind);
+                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 (C1XOptions.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 emitNegate(LIRNegate negate);
+
+    protected abstract void emitHere(CiValue dst, LIRDebugInfo info, boolean infoOnly);
+
+    protected abstract void emitMonitorAddress(int monitor, CiValue dst);
+
+    protected abstract void emitPause();
+
+    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 emitThrow(CiValue inOpr1, CiValue inOpr2, LIRDebugInfo info, boolean unwind);
+
+    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 emitOsrEntry();
+
+    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/Compiler/src/com/sun/c1x/lir/LIRBlock.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,82 @@
+/*
+ * 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.sun.c1x.lir;
+
+import com.sun.c1x.alloc.*;
+import com.sun.c1x.asm.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code LIRBlock} class definition.
+ *
+ * @author Ben L. Titzer
+ */
+public final class LIRBlock {
+
+    public LIRBlock() {
+    }
+
+    public final Label label = new Label();
+    private LIRList lir;
+
+    /**
+     * 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 CiBitMap 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 CiBitMap 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 CiBitMap 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 CiBitMap liveKill;
+
+    public int firstLirInstructionID;
+    public int lastLirInstructionID;
+    public int exceptionHandlerPCO;
+
+    public LIRList lir() {
+        return lir;
+    }
+
+    public void setLir(LIRList lir) {
+        this.lir = lir;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/lir/LIRBranch.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,162 @@
+/*
+ * 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.sun.c1x.lir;
+
+import com.sun.c1x.asm.*;
+import com.sun.c1x.ir.*;
+import com.sun.cri.ci.*;
+
+/**
+ * @author Marcelo Cintra
+ * @author Thomas Wuerthinger
+ *
+ */
+public class LIRBranch extends LIRInstruction {
+
+    private Condition cond;
+    private CiKind kind;
+    private Label label;
+
+    /**
+     * The target block of this branch.
+     */
+    private BlockBegin block;
+
+    /**
+     * This is the unordered block for a float branch.
+     */
+    private BlockBegin 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, CiKind kind, BlockBegin block) {
+        super(LIROpcode.Branch, CiValue.IllegalValue, null, false);
+        this.cond = cond;
+        this.kind = kind;
+        this.label = block.label();
+        this.block = block;
+        this.unorderedBlock = null;
+    }
+
+    public LIRBranch(Condition cond, CiKind kind, BlockBegin block, BlockBegin ublock) {
+        super(LIROpcode.CondFloatBranch, CiValue.IllegalValue, null, false);
+        this.cond = cond;
+        this.kind = kind;
+        this.label = block.label();
+        this.block = block;
+        this.unorderedBlock = ublock;
+    }
+
+    /**
+     * @return the condition
+     */
+    public Condition cond() {
+        return cond;
+    }
+
+    public Label label() {
+        return label;
+    }
+
+    public BlockBegin block() {
+        return block;
+    }
+
+    public BlockBegin unorderedBlock() {
+        return unorderedBlock;
+    }
+
+    public void changeBlock(BlockBegin b) {
+        assert block != null : "must have old block";
+        assert block.label() == label() : "must be equal";
+
+        this.block = b;
+        this.label = b.label();
+    }
+
+    public void changeUblock(BlockBegin b) {
+        assert unorderedBlock != null : "must have old block";
+        this.unorderedBlock = b;
+    }
+
+    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(BlockBegin oldBlock, BlockBegin newBlock) {
+        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/Compiler/src/com/sun/c1x/lir/LIRCall.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.lir;
+
+import java.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;
+
+/**
+ * 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/Compiler/src/com/sun/c1x/lir/LIRCompareAndSwap.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.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/Compiler/src/com/sun/c1x/lir/LIRConvert.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.lir;
+
+import com.sun.c1x.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/Compiler/src/com/sun/c1x/lir/LIRDebugInfo.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.lir;
+
+import java.util.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.ir.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+
+/**
+ * This class represents debugging and deoptimization information attached to a LIR instruction.
+ *
+ * @author Marcelo Cintra
+ * @author Thomas Wuerthinger
+ * @author Ben L. Titzer
+ */
+public class LIRDebugInfo {
+
+    public abstract static class ValueLocator {
+        public abstract CiValue getLocation(Value value);
+    }
+
+    public final FrameState state;
+    public final List<ExceptionHandler> exceptionHandlers;
+    public CiDebugInfo debugInfo;
+
+    public LIRDebugInfo(FrameState state, List<ExceptionHandler> exceptionHandlers) {
+        assert state != null;
+        this.state = state;
+        this.exceptionHandlers = exceptionHandlers;
+    }
+
+    private LIRDebugInfo(LIRDebugInfo info) {
+        this.state = info.state;
+
+        // deep copy of exception handlers
+        if (info.exceptionHandlers != null) {
+            this.exceptionHandlers = new ArrayList<ExceptionHandler>(info.exceptionHandlers.size());
+            for (ExceptionHandler h : info.exceptionHandlers) {
+                this.exceptionHandlers.add(new ExceptionHandler(h));
+            }
+        } else {
+            this.exceptionHandlers = null;
+        }
+    }
+
+    public LIRDebugInfo copy() {
+        return new LIRDebugInfo(this);
+    }
+
+    public void setOop(CiValue location, C1XCompilation compilation, CiBitMap frameRefMap, CiBitMap 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(CiBitMap 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/Compiler/src/com/sun/c1x/lir/LIRInstruction.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,549 @@
+/*
+ * 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.sun.c1x.lir;
+
+import static com.sun.c1x.C1XCompilation.*;
+
+import java.util.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.ir.*;
+import com.sun.c1x.lir.LIROperand.LIRAddressOperand;
+import com.sun.c1x.lir.LIROperand.LIRVariableOperand;
+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.
+     */
+    public 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);
+
+        C1XMetrics.LIRInstructions++;
+
+        if (opcode == LIROpcode.Move) {
+            C1XMetrics.LIRMoveInstructions++;
+        }
+        id = -1;
+        this.operands = new LIROperand[operands.length];
+        initInputsAndTemps(tempInput, temp, operands);
+
+        assert verifyOperands();
+    }
+
+    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 List<ExceptionHandler> exceptionEdges() {
+        if (info != null && info.exceptionHandlers != null) {
+            return info.exceptionHandlers;
+        }
+
+        return Collections.emptyList();
+    }
+
+    @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()) {
+            CiBitMap 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()) {
+            CiBitMap 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/Compiler/src/com/sun/c1x/lir/LIRLabel.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,71 @@
+/*
+ * 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.sun.c1x.lir;
+
+import com.sun.c1x.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/Compiler/src/com/sun/c1x/lir/LIRList.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,533 @@
+/*
+ * 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.sun.c1x.lir;
+
+import java.util.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.alloc.*;
+import com.sun.c1x.asm.*;
+import com.sun.c1x.debug.*;
+import com.sun.c1x.gen.*;
+import com.sun.c1x.globalstub.*;
+import com.sun.c1x.ir.*;
+import com.sun.c1x.lir.FrameMap.StackBlock;
+import com.sun.cri.ci.*;
+import com.sun.cri.ci.CiTargetMethod.Mark;
+import com.sun.cri.ri.*;
+import com.sun.cri.xir.CiXirAssembler.XirMark;
+import com.sun.cri.xir.*;
+
+/**
+ * This class represents a list of LIR instructions and contains factory methods for creating and appending LIR
+ * instructions to this list.
+ *
+ * @author Marcelo Cintra
+ * @author Thomas Wuerthinger
+ * @author Ben L. Titzer
+ */
+public final class LIRList {
+
+    private List<LIRInstruction> operations;
+    private final LIRGenerator generator;
+
+    private final LIROpcode runtimeCallOp;
+
+    private LIROpcode directCallOp(RiMethod method) {
+        return C1XOptions.UseConstDirectCall && method.hasCompiledCode() ? LIROpcode.ConstDirectCall : LIROpcode.DirectCall;
+    }
+
+    public LIRList(LIRGenerator generator) {
+        this.generator = generator;
+        this.operations = new ArrayList<LIRInstruction>(8);
+        runtimeCallOp = C1XOptions.UseConstDirectCall ? LIROpcode.ConstDirectCall : LIROpcode.DirectCall;
+    }
+
+    private void append(LIRInstruction op) {
+        if (C1XOptions.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 osrEntry(CiValue osrPointer) {
+        append(new LIROp0(LIROpcode.OsrEntry, osrPointer));
+    }
+
+    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 infopoint(LIROpcode opcode, CiValue dst, LIRDebugInfo info) {
+        append(new LIROp0(opcode, dst, info));
+    }
+
+    public void alloca(StackBlock stackBlock, CiValue dst) {
+        append(new LIRStackAllocate(dst, stackBlock));
+    }
+
+    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 throwException(CiValue exceptionPC, CiValue exceptionOop, LIRDebugInfo info) {
+        append(new LIROp2(LIROpcode.Throw, exceptionPC, exceptionOop, CiValue.IllegalValue, info, CiKind.Illegal, true));
+    }
+
+    public void unwindException(CiValue exceptionPC, CiValue exceptionOop, LIRDebugInfo info) {
+        append(new LIROp2(LIROpcode.Unwind, exceptionPC, exceptionOop, CiValue.IllegalValue, 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(BlockBegin block) {
+        append(new LIRBranch(Condition.TRUE, CiKind.Illegal, 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, CiKind kind, BlockBegin block) {
+        assert kind != CiKind.Float && kind != CiKind.Double : "no fp comparisons";
+        append(new LIRBranch(cond, kind, block));
+    }
+
+    public void branch(Condition cond, CiKind kind, BlockBegin block, BlockBegin unordered) {
+        assert kind == CiKind.Float || kind == CiKind.Double : "fp comparisons only";
+        append(new LIRBranch(cond, kind, block, unordered));
+    }
+
+    public void tableswitch(CiValue index, int lowKey, BlockBegin defaultTargets, BlockBegin[] 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 pause() {
+        append(new LIROp0(LIROpcode.Pause));
+    }
+
+    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(BlockBegin x) {
+        // print block id
+        BlockEnd end = x.end();
+        TTY.print("B%d ", x.blockID);
+
+        // print flags
+        if (x.checkBlockFlag(BlockBegin.BlockFlag.StandardEntry)) {
+            TTY.print("std ");
+        }
+        if (x.checkBlockFlag(BlockBegin.BlockFlag.OsrEntry)) {
+            TTY.print("osr ");
+        }
+        if (x.checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry)) {
+            TTY.print("ex ");
+        }
+        if (x.checkBlockFlag(BlockBegin.BlockFlag.SubroutineEntry)) {
+            TTY.print("jsr ");
+        }
+        if (x.checkBlockFlag(BlockBegin.BlockFlag.BackwardBranchTarget)) {
+            TTY.print("bb ");
+        }
+        if (x.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader)) {
+            TTY.print("lh ");
+        }
+        if (x.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopEnd)) {
+            TTY.print("le ");
+        }
+
+        // print block bci range
+        TTY.print("[%d, %d] ", x.bci(), (end == null ? -1 : end.bci()));
+
+        // 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);
+            }
+        }
+
+        // print exception handlers
+        if (x.numberOfExceptionHandlers() > 0) {
+            TTY.print("xhandler: ");
+            for (int i = 0; i < x.numberOfExceptionHandlers(); i++) {
+                TTY.print("B%d ", x.exceptionHandlerAt(i).blockID);
+            }
+        }
+
+        TTY.println();
+    }
+
+    public static void printLIR(List<BlockBegin> blocks) {
+        if (TTY.isSuppressed()) {
+            return;
+        }
+        TTY.println("LIR:");
+        int i;
+        for (i = 0; i < blocks.size(); i++) {
+            BlockBegin 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/Compiler/src/com/sun/c1x/lir/LIRMemoryBarrier.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.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/Compiler/src/com/sun/c1x/lir/LIRMonitorAddress.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.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/Compiler/src/com/sun/c1x/lir/LIRNegate.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.lir;
+
+import com.sun.c1x.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/Compiler/src/com/sun/c1x/lir/LIROp0.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.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/Compiler/src/com/sun/c1x/lir/LIROp1.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.lir;
+
+import com.sun.c1x.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/Compiler/src/com/sun/c1x/lir/LIROp2.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.lir;
+
+import com.sun.c1x.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/Compiler/src/com/sun/c1x/lir/LIROp3.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.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/Compiler/src/com/sun/c1x/lir/LIROpcode.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,114 @@
+/*
+ * 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.sun.c1x.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,
+        OsrEntry,
+        Here,
+        Info,
+        Alloca,
+        Breakpoint,
+        Pause,
+        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,
+        Throw,
+        Unwind,
+        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/Compiler/src/com/sun/c1x/lir/LIROperand.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.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/Compiler/src/com/sun/c1x/lir/LIRSignificantBit.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.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/Compiler/src/com/sun/c1x/lir/LIRStackAllocate.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,51 @@
+/*
+ * 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.sun.c1x.lir;
+
+import com.sun.c1x.lir.FrameMap.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+/**
+ * LIR instruction used in translating {@link Bytecodes#ALLOCA}.
+ *
+ * @author Doug Simon
+ */
+public class LIRStackAllocate extends LIRInstruction {
+
+    public final StackBlock stackBlock;
+
+    /**
+     * Creates an LIR instruction modelling a stack block allocation.
+     * @param result
+     */
+    public LIRStackAllocate(CiValue result, StackBlock stackBlock) {
+        super(LIROpcode.Alloca, result, null, false);
+        this.stackBlock = stackBlock;
+    }
+
+    @Override
+    public void emitCode(LIRAssembler masm) {
+        masm.emitStackAllocate(stackBlock, this.result());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/lir/LIRTableSwitch.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.lir;
+
+import com.sun.c1x.ir.*;
+import com.sun.cri.ci.*;
+
+/**
+ * @author Doug Simon
+ */
+public class LIRTableSwitch extends LIRInstruction {
+
+    public BlockBegin defaultTarget;
+
+    public final BlockBegin[] targets;
+
+    public final int lowKey;
+
+    public LIRTableSwitch(CiValue value, int lowKey, BlockBegin defaultTarget, BlockBegin[] 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 (BlockBegin b : targets) {
+            buf.append("\ncase ").append(key).append(": [B").append(b.blockID).append(']');
+            key++;
+        }
+        return buf.toString();
+    }
+
+    private BlockBegin substitute(BlockBegin block, BlockBegin oldBlock, BlockBegin 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(BlockBegin oldBlock, BlockBegin 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/Compiler/src/com/sun/c1x/lir/LIRXirInstruction.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,166 @@
+/*
+ * 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.sun.c1x.lir;
+
+import java.util.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.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;
+
+    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;
+
+        C1XMetrics.LIRXIRInstructions++;
+    }
+
+    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();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/lir/package-info.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.lir;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/observer/CompilationEvent.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.
+ */
+package com.sun.c1x.observer;
+
+import java.util.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.alloc.*;
+import com.sun.c1x.graph.*;
+import com.sun.c1x.ir.*;
+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 C1XCompilation compilation;
+    private final String label;
+    private BlockBegin startBlock;
+
+    private BlockMap blockMap;
+    private int codeSize = -1;
+
+    private LinearScan allocator;
+    private CiTargetMethod targetMethod;
+    private boolean hirValid = false;
+    private boolean lirValid = false;
+
+    private Interval[] intervals;
+    private int intervalsSize;
+    private Interval[] intervalsCopy = null;
+
+    public CompilationEvent(C1XCompilation compilation) {
+        this(compilation, null);
+    }
+
+    private CompilationEvent(C1XCompilation compilation, String label) {
+        assert compilation != null;
+        this.label = label;
+        this.compilation = compilation;
+    }
+
+    public CompilationEvent(C1XCompilation compilation, String label, BlockBegin startBlock, boolean hirValid, boolean lirValid) {
+        this(compilation, label);
+        this.startBlock = startBlock;
+        this.hirValid = hirValid;
+        this.lirValid = lirValid;
+    }
+
+    public CompilationEvent(C1XCompilation compilation, String label, BlockBegin startBlock, boolean hirValid, boolean lirValid, CiTargetMethod targetMethod) {
+        this(compilation, label, startBlock, hirValid, lirValid);
+        this.targetMethod = targetMethod;
+    }
+
+    public CompilationEvent(C1XCompilation compilation, String label, BlockMap blockMap, int codeSize) {
+        this(compilation, label);
+        this.blockMap = blockMap;
+        this.codeSize = codeSize;
+    }
+
+    public CompilationEvent(C1XCompilation compilation, String label, LinearScan allocator, Interval[] intervals, int intervalsSize) {
+        this(compilation, label);
+        this.allocator = allocator;
+        this.intervals = intervals;
+        this.intervalsSize = intervalsSize;
+    }
+
+    public C1XCompilation getCompilation() {
+        return compilation;
+    }
+
+    public String getLabel() {
+        return label;
+    }
+
+    public RiMethod getMethod() {
+        return compilation.method;
+    }
+
+    public BlockMap getBlockMap() {
+        return blockMap;
+    }
+
+    public BlockBegin getStartBlock() {
+        return startBlock;
+    }
+
+    public LinearScan getAllocator() {
+        return allocator;
+    }
+
+    public CiTargetMethod getTargetMethod() {
+        return targetMethod;
+    }
+
+    public boolean isHIRValid() {
+        return hirValid;
+    }
+
+    public boolean isLIRValid() {
+        return lirValid;
+    }
+
+    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;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/observer/CompilationObserver.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.c1x.observer;
+
+import com.sun.c1x.*;
+
+/**
+ * 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 C1XCompilation}.
+     *
+     * @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 C1XCompilation}.
+     *
+     * @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/Compiler/src/com/sun/c1x/observer/ObservableCompiler.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.observer;
+
+import java.util.*;
+
+import com.sun.c1x.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/Compiler/src/com/sun/c1x/observer/package-info.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.observer;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/opt/BlockMerger.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,132 @@
+/*
+ * 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.sun.c1x.opt;
+
+import com.sun.c1x.*;
+import com.sun.c1x.graph.*;
+import com.sun.c1x.ir.*;
+import com.sun.c1x.value.*;
+import com.sun.c1x.value.FrameState.*;
+
+/**
+ * This class implements block merging, which combines adjacent basic blocks into a larger
+ * basic block, and block skipping, which removes empty blocks that end in a Goto with
+ * their target.
+ *
+ * @author Ben L. Titzer
+ */
+public class BlockMerger implements BlockClosure {
+
+    private final BlockBegin startBlock;
+    private final IR ir;
+
+    public BlockMerger(IR ir) {
+        this.ir = ir;
+        startBlock = ir.startBlock;
+        startBlock.iteratePreOrder(this);
+    }
+
+    public void apply(BlockBegin block) {
+        while (block.end() instanceof Goto && block != startBlock) {
+            BlockEnd end = block.end();
+            BlockBegin sux = end.defaultSuccessor();
+
+            assert end.successors().size() == 1 : "end must have exactly one successor";
+            assert !sux.isExceptionEntry() : "should not have Goto to exception entry";
+
+            if (!end.isSafepoint()) {
+                if (sux.numberOfPreds() == 1) {
+                    // the successor has only one predecessor, merge it into this block
+                    mergeBlocks(block, sux, end);
+                    C1XMetrics.BlocksMerged++;
+                    continue;
+                } else if (C1XOptions.OptBlockSkipping && block.next() == end && !block.isExceptionEntry()) {
+                    // the successor has multiple predecessors, but this block is empty
+                    skipBlock(block, sux, end);
+                    break;
+                }
+            }
+            break;
+        }
+    }
+
+    private void skipBlock(BlockBegin block, final BlockBegin sux, BlockEnd oldEnd) {
+        final FrameState oldState = oldEnd.stateAfter();
+        assert sux.stateBefore().scope() == oldState.scope();
+        boolean hasAtLeastOnePhi = block.stateBefore().forEachPhi(block, new PhiProcedure() {
+            public boolean doPhi(Phi phi) {
+                return false;
+            }
+        });
+
+        if (hasAtLeastOnePhi) {
+            // can't skip a block that has phis
+            return;
+        }
+        for (final BlockBegin pred : block.predecessors()) {
+            final FrameState predState = pred.end().stateAfter();
+            if (predState.scope() != oldState.scope() || predState.stackSize() != oldState.stackSize()) {
+                // scopes would not match after skipping this block
+                // XXX: if phi's were smarter about scopes, this would not be necessary
+                return;
+            }
+            boolean atLeastOneSuxPhiMergesFromAnotherBlock = !sux.stateBefore().forEachPhi(sux, new PhiProcedure() {
+                public boolean doPhi(Phi phi) {
+                    if (phi.inputIn(sux.stateBefore()) != phi.inputIn(pred.end().stateAfter())) {
+                        return false;
+                    }
+                    return true;
+                }
+            });
+
+            if (atLeastOneSuxPhiMergesFromAnotherBlock) {
+                return;
+            }
+        }
+        ir.replaceBlock(block, sux);
+        C1XMetrics.BlocksSkipped++;
+    }
+
+    private void mergeBlocks(BlockBegin block, BlockBegin sux, BlockEnd oldEnd) {
+        BlockEnd newEnd;
+        // find instruction before oldEnd & append first instruction of sux block
+        Instruction prev = oldEnd.prev(block);
+        Instruction next = sux.next();
+        assert !(prev instanceof BlockEnd) : "must not be a BlockEnd";
+        prev.setNext(next, next.bci());
+        BlockUtil.disconnectFromGraph(sux);
+        newEnd = sux.end();
+        block.setEnd(newEnd);
+        // add exception handlers of deleted block, if any
+        for (BlockBegin xhandler : sux.exceptionHandlerBlocks()) {
+            block.addExceptionHandler(xhandler);
+
+            // also substitute predecessor of exception handler
+            assert xhandler.isPredecessor(sux) : "missing predecessor";
+            xhandler.removePredecessor(sux);
+            if (!xhandler.isPredecessor(block)) {
+                xhandler.addPredecessor(block);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/opt/CEEliminator.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,232 @@
+/*
+ * 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.sun.c1x.opt;
+
+import com.sun.c1x.*;
+import com.sun.c1x.graph.*;
+import com.sun.c1x.ir.*;
+import com.sun.c1x.value.*;
+import com.sun.c1x.value.FrameState.*;
+import com.sun.cri.ci.*;
+
+/**
+ * This class implements conditional-expression elimination, which replaces some
+ * simple branching constructs with conditional moves.
+ *
+ * @author Ben L. Titzer
+ */
+public class CEEliminator implements BlockClosure {
+
+    final IR ir;
+    final InstructionSubstituter subst;
+
+    public CEEliminator(IR ir) {
+        this.ir = ir;
+        this.subst = new InstructionSubstituter(ir);
+        ir.startBlock.iteratePreOrder(this);
+        subst.finish();
+    }
+
+    void adjustExceptionEdges(BlockBegin block, BlockBegin sux) {
+        int e = sux.numberOfExceptionHandlers();
+        for (int i = 0; i < e; i++) {
+            BlockBegin xhandler = sux.exceptionHandlerAt(i);
+            block.addExceptionHandler(xhandler);
+
+            assert xhandler.isPredecessor(sux) : "missing predecessor";
+            if (sux.numberOfPreds() == 0) {
+                // sux is disconnected from graph so disconnect from exception handlers
+                xhandler.removePredecessor(sux);
+            }
+            if (!xhandler.isPredecessor(block)) {
+                xhandler.addPredecessor(block);
+            }
+        }
+    }
+
+    public void apply(BlockBegin block) {
+        // 1) check that block ends with an If
+        if (!(block.end() instanceof If)) {
+            return;
+        }
+        If curIf = (If) block.end();
+
+        // check that the if's operands are of int or object type
+        CiKind ifType = curIf.x().kind;
+        if (!ifType.isInt() && !ifType.isObject()) {
+            return;
+        }
+
+        BlockBegin tBlock = curIf.trueSuccessor();
+        BlockBegin fBlock = curIf.falseSuccessor();
+        Instruction tCur = tBlock.next();
+        Instruction fCur = fBlock.next();
+
+        // one Constant may be present between BlockBegin and BlockEnd
+        Instruction tConst = null;
+        Instruction fConst = null;
+        if (tCur instanceof Constant) {
+            tConst = tCur;
+            tCur = tCur.next();
+        }
+        if (fCur instanceof Constant) {
+            fConst = fCur;
+            fCur = fCur.next();
+        }
+
+        // check that both branches end with a goto
+        if (!(tCur instanceof Goto) || !(fCur instanceof Goto)) {
+            return;
+        }
+        Goto tGoto = (Goto) tCur;
+        Goto fGoto = (Goto) fCur;
+
+        // check that both gotos merge into the same block
+        BlockBegin sux = tGoto.defaultSuccessor();
+        if (sux != fGoto.defaultSuccessor()) {
+            return;
+        }
+
+        // check that at least one word was pushed on suxState
+        FrameState suxState = sux.stateBefore();
+        if (suxState.stackSize() <= curIf.stateAfter().stackSize()) {
+            return;
+        }
+
+        // check that phi function is present at end of successor stack and that
+        // only this phi was pushed on the stack
+        final Value suxPhi = suxState.stackAt(curIf.stateAfter().stackSize());
+        if (suxPhi == null || !(suxPhi instanceof Phi) || ((Phi) suxPhi).block() != sux) {
+            return;
+        }
+        if (suxPhi.kind.sizeInSlots() != suxState.stackSize() - curIf.stateAfter().stackSize()) {
+            return;
+        }
+
+        // get the values that were pushed in the true- and false-branch
+        Value tValue = tGoto.stateAfter().stackAt(curIf.stateAfter().stackSize());
+        Value fValue = fGoto.stateAfter().stackAt(curIf.stateAfter().stackSize());
+
+        assert tValue.kind == fValue.kind : "incompatible types";
+
+        if (tValue.kind.isFloat() || tValue.kind.isDouble()) {
+            // backend does not support conditional moves on floats
+            return;
+        }
+
+        // check that successor has no other phi functions but suxPhi
+        // this can happen when tBlock or fBlock contained additional stores to local variables
+        // that are no longer represented by explicit instructions
+        boolean suxHasOtherPhi = sux.stateBefore().forEachPhi(sux, new PhiProcedure() {
+            public boolean doPhi(Phi phi) {
+                return phi == suxPhi;
+            }
+        });
+        if (suxHasOtherPhi) {
+            return;
+        }
+
+        // check that true and false blocks don't have phis
+        if (tBlock.stateBefore().hasPhis() || fBlock.stateBefore().hasPhis()) {
+            return;
+        }
+
+        // 2) cut off the original if and replace with constants and a Goto
+        // cut curIf away and get node before
+        Instruction ifPrev = curIf.prev(block);
+        int bci = curIf.bci();
+
+        // append constants of true- and false-block if necessary
+        // clone constants because original block must not be destroyed
+        assert (tValue != fConst && fValue != tConst) || tConst == fConst : "mismatch";
+        if (tValue == tConst) {
+            Constant tc = new Constant(tConst.asConstant());
+            tValue = tc;
+            ifPrev = ifPrev.setNext(tc, bci);
+        }
+        if (fValue == fConst) {
+            Constant fc = new Constant(fConst.asConstant());
+            fValue = fc;
+            ifPrev = ifPrev.setNext(fc, bci);
+        }
+
+        Value result;
+        if (tValue == fValue) {
+            // conditional chooses the same value regardless
+            result = tValue;
+            C1XMetrics.RedundantConditionals++;
+        } else {
+            // it is very unlikely that the condition can be statically decided
+            // (this was checked previously by the Canonicalizer), so always
+            // append IfOp
+            result = new IfOp(curIf.x(), curIf.condition(), curIf.y(), tValue, fValue);
+            ifPrev = ifPrev.setNext((Instruction) result, bci);
+        }
+
+        // append Goto to successor
+        FrameState stateBefore = curIf.isSafepoint() ? curIf.stateAfter() : null;
+        Goto newGoto = new Goto(sux, stateBefore, curIf.isSafepoint() || tGoto.isSafepoint() || fGoto.isSafepoint());
+
+        // prepare state for Goto
+        FrameState tempGotoState = curIf.stateAfter();
+        while (suxState.scope() != tempGotoState.scope()) {
+            tempGotoState = tempGotoState.popScope();
+            assert tempGotoState != null : "states do not match up";
+        }
+        MutableFrameState gotoState = tempGotoState.copy();
+        gotoState.push(result.kind, result);
+        assert gotoState.isSameAcrossScopes(suxState) : "states must match now";
+        // ATTN: assumption: last use of gotoState, else add .immutableCopy()
+        newGoto.setStateAfter(gotoState);
+
+        // Steal the bci for the goto from the sux
+        ifPrev = ifPrev.setNext(newGoto, sux.bci());
+
+        // update block end (will remove this block from tBlock and fBlock predecessors)
+        block.setEnd(newGoto);
+
+        // remove blocks if they became unreachable
+        tryRemove(tBlock);
+        tryRemove(fBlock);
+
+        // substitute the phi if possible
+        Phi suxAsPhi = (Phi) suxPhi;
+        if (suxAsPhi.inputCount() == 1) {
+            // if the successor block now has only one predecessor
+            assert suxAsPhi.inputAt(0) == result : "screwed up phi";
+            subst.setSubst(suxPhi, result);
+
+            // 3) successfully eliminated a conditional expression
+            C1XMetrics.ConditionalEliminations++;
+        }
+    }
+
+    private void tryRemove(BlockBegin succ) {
+        if (succ.numberOfPreds() == 0) {
+            // block just became unreachable
+            for (BlockBegin s : succ.end().successors()) {
+                s.predecessors().remove(succ);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/opt/Canonicalizer.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,1372 @@
+/*
+ * 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.sun.c1x.opt;
+
+import static com.sun.cri.bytecode.Bytecodes.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.ir.*;
+import com.sun.c1x.util.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * The {@code Canonicalizer} reduces instructions to a canonical form by folding constants,
+ * putting constants on the right side of commutative operators, simplifying conditionals,
+ * and several other transformations.
+ *
+ * @author Ben L. Titzer
+ */
+public class Canonicalizer extends DefaultValueVisitor {
+
+    final RiRuntime runtime;
+    final RiMethod method;
+    final CiTarget target;
+    Value canonical;
+    List<Instruction> extra;
+
+    public Canonicalizer(RiRuntime runtime, RiMethod method, CiTarget target) {
+        this.runtime = runtime;
+        this.method = method;
+        this.target = target;
+    }
+
+    public Value canonicalize(Instruction original) {
+        this.canonical = original;
+        this.extra = null;
+        original.accept(this);
+        return this.canonical;
+    }
+
+    public List<Instruction> extra() {
+        return extra;
+    }
+
+    private <T extends Instruction> T addInstr(T x) {
+        if (extra == null) {
+            extra = new LinkedList<Instruction>();
+        }
+        extra.add(x);
+        return x;
+    }
+
+    private Constant intInstr(int v) {
+        return addInstr(Constant.forInt(v));
+    }
+
+    private Constant longInstr(long v) {
+        return addInstr(Constant.forLong(v));
+    }
+
+    private Constant wordInstr(long v) {
+        return addInstr(Constant.forWord(v));
+    }
+
+    private Value setCanonical(Value x) {
+        return canonical = x;
+    }
+
+    private Value setIntConstant(int val) {
+        return canonical = Constant.forInt(val);
+    }
+
+    private Value setConstant(CiConstant val) {
+        return canonical = new Constant(val);
+    }
+
+    private Value setBooleanConstant(boolean val) {
+        return canonical = Constant.forBoolean(val);
+    }
+
+    private Value setObjectConstant(Object val) {
+        if (C1XOptions.SupportObjectConstants) {
+            return canonical = Constant.forObject(val);
+        }
+        return canonical;
+    }
+
+    private Value setLongConstant(long val) {
+        return canonical = Constant.forLong(val);
+    }
+
+    private Value setFloatConstant(float val) {
+        return canonical = Constant.forFloat(val);
+    }
+
+    private Value setDoubleConstant(double val) {
+        return canonical = Constant.forDouble(val);
+    }
+
+    private Value setWordConstant(long val) {
+        return canonical = Constant.forDouble(val);
+    }
+
+    private void moveConstantToRight(Op2 x) {
+        if (x.x().isConstant() && isCommutative(x.opcode)) {
+            x.swapOperands();
+        }
+    }
+
+    private void visitOp2(Op2 i) {
+        final Value x = i.x();
+        final Value y = i.y();
+
+        if (x == y) {
+            // the left and right operands are the same value, try reducing some operations
+            switch (i.opcode) {
+                case ISUB: setIntConstant(0); return;
+                case LSUB: setLongConstant(0); return;
+                case IAND: // fall through
+                case LAND: // fall through
+                case IOR:  // fall through
+                case LOR: setCanonical(x); return;
+                case IXOR: setIntConstant(0); return;
+                case LXOR: setLongConstant(0); return;
+            }
+        }
+
+        CiKind kind = x.kind;
+        if (x.isConstant() && y.isConstant()) {
+            // both operands are constants, try constant folding
+            switch (kind) {
+                case Int: {
+                    Integer val = foldIntOp2(i.opcode, x.asConstant().asInt(), y.asConstant().asInt());
+                    if (val != null) {
+                        setIntConstant(val); // the operation was successfully folded to an int
+                        return;
+                    }
+                    break;
+                }
+                case Long: {
+                    Long val = foldLongOp2(i.opcode, x.asConstant().asLong(), y.asConstant().asLong());
+                    if (val != null) {
+                        setLongConstant(val); // the operation was successfully folded to a long
+                        return;
+                    }
+                    break;
+                }
+                case Float: {
+                    if (C1XOptions.CanonicalizeFloatingPoint) {
+                        // try to fold a floating point operation
+                        Float val = foldFloatOp2(i.opcode, x.asConstant().asFloat(), y.asConstant().asFloat());
+                        if (val != null) {
+                            setFloatConstant(val); // the operation was successfully folded to a float
+                            return;
+                        }
+                    }
+                    break;
+                }
+                case Double: {
+                    if (C1XOptions.CanonicalizeFloatingPoint) {
+                        // try to fold a floating point operation
+                        Double val = foldDoubleOp2(i.opcode, x.asConstant().asDouble(), y.asConstant().asDouble());
+                        if (val != null) {
+                            setDoubleConstant(val); // the operation was successfully folded to a double
+                            return;
+                        }
+                    }
+                    break;
+                }
+                case Word: {
+                    CiConstant val = runtime.foldWordOperation(i.opcode, new CiMethodInvokeArguments() {
+                        int argIndex;
+                        @Override
+                        public CiConstant nextArg() {
+                            if (argIndex == 0) {
+                                return x.asConstant();
+                            }
+                            if (argIndex == 1) {
+                                return y.asConstant();
+                            }
+                            argIndex++;
+                            return null;
+                        }
+                    });
+
+                    if (val != null) {
+                        setConstant(val); // the operation was successfully folded to a word
+                        return;
+                    }
+                    break;
+                }
+            }
+        }
+
+        // if there is a constant on the left and the operation is commutative, move it to the right
+        moveConstantToRight(i);
+
+        if (i.y().isConstant()) {
+            // the right side is a constant, try strength reduction
+            switch (kind) {
+                case Int: {
+                    if (reduceIntOp2(i, i.x(), i.y().asConstant().asInt()) != null) {
+                        return;
+                    }
+                    break;
+                }
+                case Long: {
+                    if (reduceLongOp2(i, i.x(), i.y().asConstant().asLong()) != null) {
+                        return;
+                    }
+                    break;
+                }
+                case Word: {
+                    if (reduceWordOp2(i, i.x(), i.y().asConstant().asLong()) != null) {
+                        return;
+                    }
+                    break;
+                }
+                // XXX: note that other cases are possible, but harder
+                // floating point operations need to be extra careful
+            }
+        }
+        assert Util.archKindsEqual(i, canonical);
+    }
+
+    private Value reduceIntOp2(Op2 original, Value x, int y) {
+        // attempt to reduce a binary operation with a constant on the right
+        int opcode = original.opcode;
+        switch (opcode) {
+            case IADD: return y == 0 ? setCanonical(x) : null;
+            case ISUB: return y == 0 ? setCanonical(x) : null;
+            case IMUL: {
+                if (y == 1) {
+                    return setCanonical(x);
+                }
+                if (y > 0 && (y & y - 1) == 0 && C1XOptions.CanonicalizeMultipliesToShifts) {
+                    // strength reduce multiply by power of 2 to shift operation
+                    return setCanonical(new ShiftOp(ISHL, x, intInstr(CiUtil.log2(y))));
+                }
+                return y == 0 ? setIntConstant(0) : null;
+            }
+            case IDIV: return y == 1 ? setCanonical(x) : null;
+            case IREM: return y == 1 ? setCanonical(x) : null;
+            case IAND: {
+                if (y == -1) {
+                    return setCanonical(x);
+                }
+                return y == 0 ? setIntConstant(0) : null;
+            }
+            case IOR: {
+                if (y == -1) {
+                    return setIntConstant(-1);
+                }
+                return y == 0 ? setCanonical(x) : null;
+            }
+            case IXOR: return y == 0 ? setCanonical(x) : null;
+            case ISHL: return reduceShift(false, opcode, IUSHR, x, y);
+            case ISHR: return reduceShift(false, opcode, 0, x, y);
+            case IUSHR: return reduceShift(false, opcode, ISHL, x, y);
+        }
+        return null;
+    }
+
+    private Value reduceShift(boolean islong, int opcode, int reverse, Value x, long y) {
+        int mod = islong ? 0x3f : 0x1f;
+        long shift = y & mod;
+        if (shift == 0) {
+            return setCanonical(x);
+        }
+        if (x instanceof ShiftOp) {
+            // this is a chained shift operation ((e shift e) shift K)
+            ShiftOp s = (ShiftOp) x;
+            if (s.y().isConstant()) {
+                long z = s.y().asConstant().asLong();
+                if (s.opcode == opcode) {
+                    // this is a chained shift operation (e >> C >> K)
+                    y = y + z;
+                    shift = y & mod;
+                    if (shift == 0) {
+                        return setCanonical(s.x());
+                    }
+                    // reduce to (e >> (C + K))
+                    return setCanonical(new ShiftOp(opcode, s.x(), intInstr((int) shift)));
+                }
+                if (s.opcode == reverse && y == z) {
+                    // this is a chained shift of the form (e >> K << K)
+                    if (islong) {
+                        long mask = -1;
+                        if (opcode == LUSHR) {
+                            mask = mask >>> y;
+                        } else {
+                            mask = mask << y;
+                        }
+                        // reduce to (e & mask)
+                        return setCanonical(new LogicOp(LAND, s.x(), longInstr(mask)));
+                    } else {
+                        int mask = -1;
+                        if (opcode == IUSHR) {
+                            mask = mask >>> y;
+                        } else {
+                            mask = mask << y;
+                        }
+                        return setCanonical(new LogicOp(IAND, s.x(), intInstr(mask)));
+                    }
+                }
+            }
+        }
+        if (y != shift) {
+            // (y & mod) != y
+            return setCanonical(new ShiftOp(opcode, x, intInstr((int) shift)));
+        }
+        return null;
+    }
+
+    private Value reduceLongOp2(Op2 original, Value x, long y) {
+        // attempt to reduce a binary operation with a constant on the right
+        int opcode = original.opcode;
+        switch (opcode) {
+            case LADD: return y == 0 ? setCanonical(x) : null;
+            case LSUB: return y == 0 ? setCanonical(x) : null;
+            case LMUL: {
+                if (y == 1) {
+                    return setCanonical(x);
+                }
+                if (y > 0 && (y & y - 1) == 0 && C1XOptions.CanonicalizeMultipliesToShifts) {
+                    // strength reduce multiply by power of 2 to shift operation
+                    return setCanonical(new ShiftOp(LSHL, x, intInstr(CiUtil.log2(y))));
+                }
+                return y == 0 ? setLongConstant(0) : null;
+            }
+            case LDIV: return y == 1 ? setCanonical(x) : null;
+            case LREM: return y == 1 ? setCanonical(x) : null;
+            case LAND: {
+                if (y == -1) {
+                    return setCanonical(x);
+                }
+                return y == 0 ? setLongConstant(0) : null;
+            }
+            case LOR: {
+                if (y == -1) {
+                    return setLongConstant(-1);
+                }
+                return y == 0 ? setCanonical(x) : null;
+            }
+            case LXOR: return y == 0 ? setCanonical(x) : null;
+            case LSHL: return reduceShift(true, opcode, LUSHR, x, y);
+            case LSHR: return reduceShift(true, opcode, 0, x, y);
+            case LUSHR: return reduceShift(true, opcode, LSHL, x, y);
+        }
+        return null;
+    }
+
+    private Value reduceWordOp2(Op2 original, Value x, long y) {
+        if (y == 0) {
+            // Defer to arithmetic exception at runtime
+            return null;
+        }
+        // attempt to reduce a binary operation with a constant on the right
+        int opcode = original.opcode;
+        switch (opcode) {
+            case WDIVI:
+            case WDIV: {
+                if (y == 1) {
+                    return setCanonical(x);
+                }
+                if (CiUtil.isPowerOf2(y)) {
+                    return setCanonical(new ShiftOp(target.arch.is64bit() ? LUSHR : IUSHR, x, intInstr(CiUtil.log2(y))));
+                }
+                break;
+            }
+            case WREMI: {
+                if (y == 1) {
+                    return setCanonical(intInstr(0));
+                }
+                if (CiUtil.isPowerOf2(y)) {
+                    int mask = (int) y - 1;
+                    if (target.arch.is64bit()) {
+                        Convert l2i = new Convert(L2I, x, CiKind.Int);
+                        addInstr(l2i);
+                        return setCanonical(new LogicOp(IAND, l2i, intInstr(mask)));
+                    }
+                    return setCanonical(new LogicOp(CiKind.Int, IAND, x, intInstr(mask)));
+                }
+                break;
+            }
+            case WREM: {
+                if (y == 1) {
+                    return setCanonical(wordInstr(0));
+                }
+                if (CiUtil.isPowerOf2(y)) {
+                    if (target.arch.is64bit()) {
+                        long mask = y - 1L;
+                        return setCanonical(new LogicOp(LAND, x, longInstr(mask)));
+                    }
+                    int mask = (int) y - 1;
+                    return setCanonical(new LogicOp(IAND, x, intInstr(mask)));
+                }
+                break;
+            }
+        }
+        return null;
+    }
+
+    private boolean inCurrentBlock(Value x) {
+        if (x instanceof Instruction) {
+            Instruction i = (Instruction) x;
+            int max = 4; // XXX: anything special about 4? seems like a tunable heuristic
+            while (max > 0 && i != null && !(i instanceof BlockEnd)) {
+                i = i.next();
+                max--;
+            }
+            return i == null;
+        }
+        return true;
+    }
+
+    private Value eliminateNarrowing(CiKind kind, Convert c) {
+        Value nv = null;
+        switch (c.opcode) {
+            case I2B:
+                if (kind == CiKind.Byte) {
+                    nv = c.value();
+                }
+                break;
+            case I2S:
+                if (kind == CiKind.Short || kind == CiKind.Byte) {
+                    nv = c.value();
+                }
+                break;
+            case I2C:
+                if (kind == CiKind.Char || kind == CiKind.Byte) {
+                    nv = c.value();
+                }
+                break;
+        }
+        return nv;
+    }
+
+    @Override
+    public void visitLoadField(LoadField i) {
+        if (!i.isLoaded() || !C1XOptions.CanonicalizeConstantFields) {
+            return;
+        }
+        if (i.isStatic()) {
+            RiField field = i.field();
+            CiConstant value = field.constantValue(null);
+            if (value != null) {
+                if (method.isClassInitializer()) {
+                    // don't do canonicalization in the <clinit> method
+                    return;
+                }
+                setConstant(value);
+            }
+        } else {
+            RiField field = i.field();
+            if (i.object().isConstant()) {
+                CiConstant value = field.constantValue(i.object().asConstant());
+                if (value != null) {
+                    setConstant(value);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void visitStoreField(StoreField i) {
+        if (C1XOptions.CanonicalizeNarrowingInStores) {
+            // Eliminate narrowing conversions emitted by javac which are unnecessary when
+            // writing the value to a field that is packed
+            Value v = i.value();
+            if (v instanceof Convert) {
+                Value nv = eliminateNarrowing(i.field().kind(), (Convert) v);
+                // limit this optimization to the current basic block
+                // XXX: why is this limited to the current block?
+                if (nv != null && inCurrentBlock(v)) {
+                    setCanonical(new StoreField(i.object(), i.field(), nv, i.isStatic(),
+                                                i.stateBefore(), i.isLoaded()));
+                }
+            }
+        }
+    }
+
+    @Override
+    public void visitArrayLength(ArrayLength i) {
+        // we can compute the length of the array statically if the object
+        // is a NewArray of a constant, or if the object is a constant reference
+        // (either by itself or loaded from a constant value field)
+        Value array = i.array();
+        if (array instanceof NewArray) {
+            // the array is a NewArray; check if it has a constant length
+            NewArray newArray = (NewArray) array;
+            Value length = newArray.length();
+            if (length instanceof Constant) {
+                // note that we don't use the Constant instruction itself
+                // as that would cause problems with liveness later
+                int actualLength = length.asConstant().asInt();
+                setIntConstant(actualLength);
+            }
+        } else if (array instanceof LoadField) {
+            // the array is a load of a field; check if it is a constant
+            LoadField load = (LoadField) array;
+            CiConstant cons = load.constantValue();
+            if (cons != null && cons.isNonNull()) {
+                setIntConstant(runtime.getArrayLength(cons));
+            }
+        } else if (array.isConstant()) {
+            // the array itself is a constant object reference
+            CiConstant obj = array.asConstant();
+            if (obj.isNonNull()) {
+                setIntConstant(runtime.getArrayLength(obj));
+            }
+        }
+    }
+
+    @Override
+    public void visitStoreIndexed(StoreIndexed i) {
+        Value array = i.array();
+        Value value = i.value();
+        if (C1XOptions.CanonicalizeNarrowingInStores) {
+            // Eliminate narrowing conversions emitted by javac which are unnecessary when
+            // writing the value to an array (which is packed)
+            Value v = value;
+            if (v instanceof Convert) {
+                Value nv = eliminateNarrowing(i.elementKind(), (Convert) v);
+                if (nv != null && inCurrentBlock(v)) {
+                    setCanonical(new StoreIndexed(array, i.index(), i.length(), i.elementKind(), nv, i.stateBefore()));
+                }
+            }
+        }
+        if (C1XOptions.CanonicalizeArrayStoreChecks && i.elementKind() == CiKind.Object) {
+            if (value.isNullConstant()) {
+                i.eliminateStoreCheck();
+            } else {
+                RiType exactType = array.exactType();
+                if (exactType != null && exactType.isResolved()) {
+                    if (exactType.componentType().superType() == null) {
+                        // the exact type of the array is Object[] => no check is necessary
+                        i.eliminateStoreCheck();
+                    } else {
+                        RiType declaredType = value.declaredType();
+                        if (declaredType != null && declaredType.isResolved() && declaredType.isSubtypeOf(exactType.componentType())) {
+                            // the value being stored has a known type
+                            i.eliminateStoreCheck();
+                        }
+                    }
+                }
+            }
+        }
+        if (i.index().isConstant() && i.length() != null && i.length().isConstant()) {
+            int index = i.index().asConstant().asInt();
+            if (index >= 0 && index < i.length().asConstant().asInt()) {
+                i.eliminateBoundsCheck();
+            }
+        }
+    }
+
+    @Override
+    public void visitLoadIndexed(LoadIndexed i) {
+        if (i.index().isConstant() && i.length() != null && i.length().isConstant()) {
+            int index = i.index().asConstant().asInt();
+            if (index >= 0 && index < i.length().asConstant().asInt()) {
+                i.eliminateBoundsCheck();
+            }
+        }
+    }
+
+    @Override
+    public void visitNegateOp(NegateOp i) {
+        CiKind vt = i.x().kind;
+        Value v = i.x();
+        if (i.x().isConstant()) {
+            switch (vt) {
+                case Int: setIntConstant(-v.asConstant().asInt()); break;
+                case Long: setLongConstant(-v.asConstant().asLong()); break;
+                case Float: setFloatConstant(-v.asConstant().asFloat()); break;
+                case Double: setDoubleConstant(-v.asConstant().asDouble()); break;
+            }
+        }
+        assert vt == canonical.kind;
+    }
+
+    @Override
+    public void visitArithmeticOp(ArithmeticOp i) {
+        visitOp2(i);
+    }
+
+    @Override
+    public void visitShiftOp(ShiftOp i) {
+        visitOp2(i);
+    }
+
+    @Override
+    public void visitLogicOp(LogicOp i) {
+        visitOp2(i);
+    }
+
+    @Override
+    public void visitCompareOp(CompareOp i) {
+        if (i.kind.isVoid()) {
+            return;
+        }
+        // we can reduce a compare op if the two inputs are the same,
+        // or if both are constants
+        Value x = i.x();
+        Value y = i.y();
+        CiKind xt = x.kind;
+        if (x == y) {
+            // x and y are generated by the same instruction
+            switch (xt) {
+                case Long: setIntConstant(0); return;
+                case Float:
+                    if (x.isConstant()) {
+                        float xval = x.asConstant().asFloat(); // get the actual value of x (and y since x == y)
+                        Integer val = foldFloatCompare(i.opcode, xval, xval);
+                        assert val != null : "invalid opcode in float compare op";
+                        setIntConstant(val);
+                        return;
+                    }
+                    break;
+                case Double:
+                    if (x.isConstant()) {
+                        double xval = x.asConstant().asDouble(); // get the actual value of x (and y since x == y)
+                        Integer val = foldDoubleCompare(i.opcode, xval, xval);
+                        assert val != null : "invalid opcode in double compare op";
+                        setIntConstant(val);
+                        return;
+                    }
+                    break;
+                // note that there are no integer CompareOps
+            }
+        }
+        if (x.isConstant() && y.isConstant()) {
+            // both x and y are constants
+            switch (xt) {
+                case Long:
+                    setIntConstant(foldLongCompare(x.asConstant().asLong(), y.asConstant().asLong()));
+                    break;
+                case Float: {
+                    Integer val = foldFloatCompare(i.opcode, x.asConstant().asFloat(), y.asConstant().asFloat());
+                    assert val != null : "invalid opcode in float compare op";
+                    setIntConstant(val);
+                    break;
+                }
+                case Double: {
+                    Integer val = foldDoubleCompare(i.opcode, x.asConstant().asDouble(), y.asConstant().asDouble());
+                    assert val != null : "invalid opcode in float compare op";
+                    setIntConstant(val);
+                    break;
+                }
+            }
+        }
+        assert Util.archKindsEqual(i, canonical);
+    }
+
+    @Override
+    public void visitIfOp(IfOp i) {
+        moveConstantToRight(i);
+    }
+
+    @Override
+    public void visitConvert(Convert i) {
+        Value v = i.value();
+        if (v.isConstant()) {
+            // fold conversions between primitive types
+            // Checkstyle: stop
+            switch (i.opcode) {
+                case I2B: setIntConstant   ((byte)   v.asConstant().asInt()); return;
+                case I2S: setIntConstant   ((short)  v.asConstant().asInt()); return;
+                case I2C: setIntConstant   ((char)   v.asConstant().asInt()); return;
+                case I2L: setLongConstant  (         v.asConstant().asInt()); return;
+                case I2F: setFloatConstant (         v.asConstant().asInt()); return;
+                case L2I: setIntConstant   ((int)    v.asConstant().asLong()); return;
+                case L2F: setFloatConstant (         v.asConstant().asLong()); return;
+                case L2D: setDoubleConstant(         v.asConstant().asLong()); return;
+                case F2D: setDoubleConstant(         v.asConstant().asFloat()); return;
+                case F2I: setIntConstant   ((int)    v.asConstant().asFloat()); return;
+                case F2L: setLongConstant  ((long)   v.asConstant().asFloat()); return;
+                case D2F: setFloatConstant ((float)  v.asConstant().asDouble()); return;
+                case D2I: setIntConstant   ((int)    v.asConstant().asDouble()); return;
+                case D2L: setLongConstant  ((long)   v.asConstant().asDouble()); return;
+            }
+            // Checkstyle: resume
+        }
+
+        CiKind kind = CiKind.Illegal;
+        if (v instanceof LoadField) {
+            // remove redundant conversions from field loads of the correct type
+            kind = ((LoadField) v).field().kind();
+        } else if (v instanceof LoadIndexed) {
+            // remove redundant conversions from array loads of the correct type
+            kind = ((LoadIndexed) v).elementKind();
+        } else if (v instanceof Convert) {
+            // remove chained redundant conversions
+            Convert c = (Convert) v;
+            switch (c.opcode) {
+                case I2B: kind = CiKind.Byte; break;
+                case I2S: kind = CiKind.Short; break;
+                case I2C: kind = CiKind.Char; break;
+            }
+        }
+
+        if (kind != CiKind.Illegal) {
+            // if any of the above matched
+            switch (i.opcode) {
+                case I2B:
+                    if (kind == CiKind.Byte) {
+                        setCanonical(v);
+                    }
+                    break;
+                case I2S:
+                    if (kind == CiKind.Byte || kind == CiKind.Short) {
+                        setCanonical(v);
+                    }
+                    break;
+                case I2C:
+                    if (kind == CiKind.Char) {
+                        setCanonical(v);
+                    }
+                    break;
+            }
+        }
+
+        if (v instanceof Op2) {
+            // check if the operation was IAND with a constant; it may have narrowed the value already
+            Op2 op = (Op2) v;
+            // constant should be on right hand side if there is one
+            if (op.opcode == IAND && op.y().isConstant()) {
+                int safebits = 0;
+                int mask = op.y().asConstant().asInt();
+                switch (i.opcode) {
+                    case I2B: safebits = 0x7f; break;
+                    case I2S: safebits = 0x7fff; break;
+                    case I2C: safebits = 0xffff; break;
+                }
+                if (safebits != 0 && (mask & ~safebits) == 0) {
+                    // the mask already cleared all the upper bits necessary.
+                    setCanonical(v);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void visitNullCheck(NullCheck i) {
+        Value o = i.object();
+        if (o.isNonNull()) {
+            // if the instruction producing the object was a new, no check is necessary
+            setCanonical(o);
+        } else if (o.isConstant()) {
+            // if the object is a constant, check if it is nonnull
+            CiConstant c = o.asConstant();
+            if (c.kind.isObject() && !c.isNull()) {
+                setCanonical(o);
+            }
+        }
+    }
+
+    @Override
+    public void visitInvoke(Invoke i) {
+        if (C1XOptions.CanonicalizeFoldableMethods) {
+            RiMethod method = i.target();
+            if (method.isResolved()) {
+                // only try to fold resolved method invocations
+                CiConstant result = foldInvocation(runtime, i.target(), i.arguments());
+                if (result != null) {
+                    // folding was successful
+                    setCanonical(new Constant(result));
+                }
+            }
+        }
+    }
+
+    @Override
+    public void visitCheckCast(CheckCast i) {
+        // we can remove a redundant check cast if it is an object constant or the exact type is known
+        if (i.targetClass().isResolved()) {
+            Value o = i.object();
+            RiType type = o.exactType();
+            if (type == null) {
+                type = o.declaredType();
+            }
+            if (type != null && type.isResolved() && type.isSubtypeOf(i.targetClass())) {
+                // cast is redundant if exact type or declared type is already a subtype of the target type
+                setCanonical(o);
+            }
+            if (o.isConstant()) {
+                final CiConstant obj = o.asConstant();
+                if (obj.isNull()) {
+                    // checkcast of null is null
+                    setCanonical(o);
+                } else if (C1XOptions.CanonicalizeObjectCheckCast) {
+                    if (i.targetClass().isInstance(obj)) {
+                        // fold the cast if it will succeed
+                        setCanonical(o);
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    public void visitInstanceOf(InstanceOf i) {
+        // we can fold an instanceof if it is an object constant or the exact type is known
+        if (i.targetClass().isResolved()) {
+            Value o = i.object();
+            RiType exact = o.exactType();
+            if (exact != null && exact.isResolved() && o.isNonNull()) {
+                setIntConstant(exact.isSubtypeOf(i.targetClass()) ? 1 : 0);
+            } else if (o.isConstant()) {
+                final CiConstant obj = o.asConstant();
+                if (obj.isNull()) {
+                    // instanceof of null is false
+                    setIntConstant(0);
+                } else if (C1XOptions.CanonicalizeObjectInstanceOf) {
+                    // fold the instanceof test
+                    setIntConstant(i.targetClass().isInstance(obj) ? 1 : 0);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void visitIntrinsic(Intrinsic i) {
+        if (!C1XOptions.CanonicalizeIntrinsics) {
+            return;
+        }
+        if (!foldIntrinsic(i)) {
+            // folding did not work, try recognizing special intrinsics
+            reduceIntrinsic(i);
+        }
+        assert Util.archKindsEqual(i, canonical);
+    }
+
+    private void reduceIntrinsic(Intrinsic i) {
+        Value[] args = i.arguments();
+        C1XIntrinsic intrinsic = i.intrinsic();
+        if (intrinsic == C1XIntrinsic.java_lang_Class$isInstance) {
+            // try to convert a call to Class.isInstance() into an InstanceOf
+            RiType type = getTypeOf(args[0]);
+            if (type != null) {
+                setCanonical(new InstanceOf(type, Constant.forObject(type.getEncoding(RiType.Representation.TypeInfo)), args[1], i.stateBefore()));
+                return;
+            }
+        }
+        if (intrinsic == C1XIntrinsic.java_lang_reflect_Array$newArray) {
+            // try to convert a call to Array.newInstance() into a NewObjectArray or NewTypeArray
+            RiType type = getTypeOf(args[0]);
+            if (type != null) {
+                if (type.kind() == CiKind.Object) {
+                    setCanonical(new NewObjectArray(type, args[1], i.stateBefore()));
+                } else {
+                    RiType elementType = runtime.asRiType(type.kind());
+                    setCanonical(new NewTypeArray(args[1], elementType, i.stateBefore()));
+                }
+                return;
+            }
+        }
+        assert Util.archKindsEqual(i, canonical);
+    }
+
+    private boolean foldIntrinsic(Intrinsic i) {
+        Value[] args = i.arguments();
+        for (Value arg : args) {
+            if (arg != null && !arg.isConstant()) {
+                // one input is not constant, give up
+                return true;
+            }
+        }
+        switch (i.intrinsic()) {
+            // do not use reflection here due to efficiency and potential bootstrap problems
+            case java_lang_Object$hashCode: {
+                Object object = argAsObject(args, 0);
+                if (object != null) {
+                    setIntConstant(System.identityHashCode(object));
+                }
+                return true;
+            }
+            case java_lang_Object$getClass: {
+                Object object = argAsObject(args, 0);
+                if (object != null) {
+                    setObjectConstant(object.getClass());
+                }
+                return true;
+            }
+
+            // java.lang.Class
+            case java_lang_Class$isAssignableFrom: {
+                Class<?> javaClass = argAsClass(args, 0);
+                Class<?> otherClass = argAsClass(args, 1);
+                if (javaClass != null && otherClass != null) {
+                    setBooleanConstant(javaClass.isAssignableFrom(otherClass));
+                }
+                return true;
+            }
+            case java_lang_Class$isInstance: {
+                Class<?> javaClass = argAsClass(args, 0);
+                Object object = argAsObject(args, 1);
+                if (javaClass != null && object != null) {
+                    setBooleanConstant(javaClass.isInstance(object));
+                }
+                return true;
+            }
+            case java_lang_Class$getModifiers: {
+                Class<?> javaClass = argAsClass(args, 0);
+                if (javaClass != null) {
+                    setIntConstant(javaClass.getModifiers());
+                }
+                return true;
+            }
+            case java_lang_Class$isInterface: {
+                Class<?> javaClass = argAsClass(args, 0);
+                if (javaClass != null) {
+                    setBooleanConstant(javaClass.isInterface());
+                }
+                return true;
+            }
+            case java_lang_Class$isArray: {
+                Class<?> javaClass = argAsClass(args, 0);
+                if (javaClass != null) {
+                    setBooleanConstant(javaClass.isArray());
+                }
+                return true;
+            }
+            case java_lang_Class$isPrimitive: {
+                Class<?> javaClass = argAsClass(args, 0);
+                if (javaClass != null) {
+                    setBooleanConstant(javaClass.isPrimitive());
+                }
+                return true;
+            }
+            case java_lang_Class$getSuperclass: {
+                Class<?> javaClass = argAsClass(args, 0);
+                if (javaClass != null) {
+                    setObjectConstant(javaClass.getSuperclass());
+                }
+                return true;
+            }
+            case java_lang_Class$getComponentType: {
+                Class<?> javaClass = argAsClass(args, 0);
+                if (javaClass != null) {
+                    setObjectConstant(javaClass.getComponentType());
+                }
+                return true;
+            }
+
+            // java.lang.Math
+            case java_lang_Math$abs:   setDoubleConstant(Math.abs(argAsDouble(args, 0))); return true;
+            case java_lang_Math$sin:   setDoubleConstant(Math.sin(argAsDouble(args, 0))); return true;
+            case java_lang_Math$cos:   setDoubleConstant(Math.cos(argAsDouble(args, 0))); return true;
+            case java_lang_Math$tan:   setDoubleConstant(Math.tan(argAsDouble(args, 0))); return true;
+            case java_lang_Math$atan2: setDoubleConstant(Math.atan2(argAsDouble(args, 0), argAsDouble(args, 2))); return true;
+            case java_lang_Math$sqrt:  setDoubleConstant(Math.sqrt(argAsDouble(args, 0))); return true;
+            case java_lang_Math$log:   setDoubleConstant(Math.log(argAsDouble(args, 0))); return true;
+            case java_lang_Math$log10: setDoubleConstant(Math.log10(argAsDouble(args, 0))); return true;
+            case java_lang_Math$pow:   setDoubleConstant(Math.pow(argAsDouble(args, 0), argAsDouble(args, 2))); return true;
+            case java_lang_Math$exp:   setDoubleConstant(Math.exp(argAsDouble(args, 0))); return true;
+            case java_lang_Math$min:   setIntConstant(Math.min(argAsInt(args, 0), argAsInt(args, 1))); return true;
+            case java_lang_Math$max:   setIntConstant(Math.max(argAsInt(args, 0), argAsInt(args, 1))); return true;
+
+            // java.lang.Float
+            case java_lang_Float$floatToRawIntBits: setIntConstant(Float.floatToRawIntBits(argAsFloat(args, 0))); return true;
+            case java_lang_Float$floatToIntBits: setIntConstant(Float.floatToIntBits(argAsFloat(args, 0))); return true;
+            case java_lang_Float$intBitsToFloat: setFloatConstant(Float.intBitsToFloat(argAsInt(args, 0))); return true;
+
+            // java.lang.Double
+            case java_lang_Double$doubleToRawLongBits: setLongConstant(Double.doubleToRawLongBits(argAsDouble(args, 0))); return true;
+            case java_lang_Double$doubleToLongBits: setLongConstant(Double.doubleToLongBits(argAsDouble(args, 0))); return true;
+            case java_lang_Double$longBitsToDouble: setDoubleConstant(Double.longBitsToDouble(argAsLong(args, 0))); return true;
+
+            // java.lang.Integer
+            case java_lang_Integer$bitCount: setIntConstant(Integer.bitCount(argAsInt(args, 0))); return true;
+            case java_lang_Integer$reverseBytes: setIntConstant(Integer.reverseBytes(argAsInt(args, 0))); return true;
+
+            // java.lang.Long
+            case java_lang_Long$bitCount: setIntConstant(Long.bitCount(argAsLong(args, 0))); return true;
+            case java_lang_Long$reverseBytes: setLongConstant(Long.reverseBytes(argAsLong(args, 0))); return true;
+
+            // java.lang.System
+            case java_lang_System$identityHashCode: {
+                Object object = argAsObject(args, 0);
+                if (object != null) {
+                    setIntConstant(System.identityHashCode(object));
+                }
+                return true;
+            }
+
+            // java.lang.reflect.Array
+            case java_lang_reflect_Array$getLength: {
+                Object object = argAsObject(args, 0);
+                if (object != null && object.getClass().isArray()) {
+                    setIntConstant(Array.getLength(object));
+                }
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public void visitIf(If i) {
+        if (i.x().isConstant()) {
+            // move constant to the right
+            i.swapOperands();
+        }
+        Value l = i.x();
+        Value r = i.y();
+
+        if (l == r && !l.kind.isFloatOrDouble()) {
+            // this is a comparison of x op x
+            // No opt for float/double due to NaN case
+            reduceReflexiveIf(i);
+            return;
+        }
+
+        CiKind rt = r.kind;
+
+        Condition ifcond = i.condition();
+        if (l.isConstant() && r.isConstant()) {
+            // fold comparisons between constants and convert to Goto
+            Boolean result = ifcond.foldCondition(l.asConstant(), r.asConstant(), runtime);
+            if (result != null) {
+                setCanonical(new Goto(i.successor(result), i.stateAfter(), i.isSafepoint()));
+                return;
+            }
+        }
+
+        if (r.isConstant() && rt.isInt()) {
+            // attempt to reduce comparisons with constant on right side
+            if (l instanceof CompareOp) {
+                // attempt to reduce If ((a cmp b) op const)
+                reduceIfCompareOpConstant(i, r.asConstant());
+            }
+        }
+
+        if (isNullConstant(r) && l.isNonNull()) {
+            // this is a comparison of null against something that is not null
+            if (ifcond == Condition.EQ) {
+                // new() == null is always false
+                setCanonical(new Goto(i.falseSuccessor(), i.stateAfter(), i.isSafepoint()));
+            } else if (ifcond == Condition.NE) {
+                // new() != null is always true
+                setCanonical(new Goto(i.trueSuccessor(), i.stateAfter(), i.isSafepoint()));
+            }
+        }
+    }
+
+    private boolean isNullConstant(Value r) {
+        return r.isConstant() && r.asConstant().isNull();
+    }
+
+    private void reduceIfCompareOpConstant(If i, CiConstant rtc) {
+        Condition ifcond = i.condition();
+        Value l = i.x();
+        CompareOp cmp = (CompareOp) l;
+        boolean unorderedIsLess = cmp.opcode == FCMPL || cmp.opcode == DCMPL;
+        BlockBegin lssSucc = i.successor(ifcond.foldCondition(CiConstant.forInt(-1), rtc, runtime));
+        BlockBegin eqlSucc = i.successor(ifcond.foldCondition(CiConstant.forInt(0), rtc, runtime));
+        BlockBegin gtrSucc = i.successor(ifcond.foldCondition(CiConstant.forInt(1), rtc, runtime));
+        BlockBegin nanSucc = unorderedIsLess ? lssSucc : gtrSucc;
+        // Note: At this point all successors (lssSucc, eqlSucc, gtrSucc, nanSucc) are
+        //       equal to x->tsux() or x->fsux(). Furthermore, nanSucc equals either
+        //       lssSucc or gtrSucc.
+        if (lssSucc == eqlSucc && eqlSucc == gtrSucc) {
+            // all successors identical => simplify to: Goto
+            setCanonical(new Goto(lssSucc, i.stateAfter(), i.isSafepoint()));
+        } else {
+            // two successors differ and two successors are the same => simplify to: If (x cmp y)
+            // determine new condition & successors
+            Condition cond;
+            BlockBegin tsux;
+            BlockBegin fsux;
+            if (lssSucc == eqlSucc) {
+                cond = Condition.LE;
+                tsux = lssSucc;
+                fsux = gtrSucc;
+            } else if (lssSucc == gtrSucc) {
+                cond = Condition.NE;
+                tsux = lssSucc;
+                fsux = eqlSucc;
+            } else if (eqlSucc == gtrSucc) {
+                cond = Condition.GE;
+                tsux = eqlSucc;
+                fsux = lssSucc;
+            } else {
+                throw Util.shouldNotReachHere();
+            }
+            // TODO: the state after is incorrect here: should it be preserved from the original if?
+            If canon = new If(cmp.x(), cond, nanSucc == tsux, cmp.y(), tsux, fsux, cmp.stateBefore(), i.isSafepoint());
+            if (cmp.x() == cmp.y()) {
+                // re-canonicalize the new if
+                visitIf(canon);
+            } else {
+                setCanonical(canon);
+            }
+        }
+    }
+
+    private void reduceReflexiveIf(If i) {
+        // simplify reflexive comparisons If (x op x) to Goto
+        BlockBegin succ;
+        switch (i.condition()) {
+            case EQ: succ = i.successor(true); break;
+            case NE: succ = i.successor(false); break;
+            case LT: succ = i.successor(false); break;
+            case LE: succ = i.successor(true); break;
+            case GT: succ = i.successor(false); break;
+            case GE: succ = i.successor(true); break;
+            default:
+                throw Util.shouldNotReachHere();
+        }
+        setCanonical(new Goto(succ, i.stateAfter(), i.isSafepoint()));
+    }
+
+    @Override
+    public void visitTableSwitch(TableSwitch i) {
+        Value v = i.value();
+        if (v.isConstant()) {
+            // fold a table switch over a constant by replacing it with a goto
+            int val = v.asConstant().asInt();
+            BlockBegin succ = i.defaultSuccessor();
+            if (val >= i.lowKey() && val <= i.highKey()) {
+                succ = i.successors().get(val - i.lowKey());
+            }
+            setCanonical(new Goto(succ, i.stateAfter(), i.isSafepoint()));
+            return;
+        }
+        int max = i.numberOfCases();
+        if (max == 0) {
+            // replace switch with Goto
+            if (v instanceof Instruction) {
+                // TODO: is it necessary to add the instruction explicitly?
+                addInstr((Instruction) v);
+            }
+            setCanonical(new Goto(i.defaultSuccessor(), i.stateAfter(), i.isSafepoint()));
+            return;
+        }
+        if (max == 1) {
+            // replace switch with If
+            Constant key = intInstr(i.lowKey());
+            If newIf = new If(v, Condition.EQ, false, key, i.successors().get(0), i.defaultSuccessor(), null, i.isSafepoint());
+            newIf.setStateAfter(i.stateAfter());
+            setCanonical(newIf);
+        }
+    }
+
+    @Override
+    public void visitLookupSwitch(LookupSwitch i) {
+        Value v = i.value();
+        if (v.isConstant()) {
+            // fold a lookup switch over a constant by replacing it with a goto
+            int val = v.asConstant().asInt();
+            BlockBegin succ = i.defaultSuccessor();
+            for (int j = 0; j < i.numberOfCases(); j++) {
+                if (val == i.keyAt(j)) {
+                    succ = i.successors().get(j);
+                    break;
+                }
+            }
+            setCanonical(new Goto(succ, i.stateAfter(), i.isSafepoint()));
+            return;
+        }
+        int max = i.numberOfCases();
+        if (max == 0) {
+            // replace switch with Goto
+            if (v instanceof Instruction) {
+                addInstr((Instruction) v); // the value expression may produce side effects
+            }
+            setCanonical(new Goto(i.defaultSuccessor(), i.stateAfter(), i.isSafepoint()));
+            return;
+        }
+        if (max == 1) {
+            // replace switch with If
+            Constant key = intInstr(i.keyAt(0));
+            If newIf = new If(v, Condition.EQ, false, key, i.successors().get(0), i.defaultSuccessor(), null, i.isSafepoint());
+            newIf.setStateAfter(i.stateAfter());
+            setCanonical(newIf);
+        }
+    }
+
+    private void visitUnsafeRawOp(UnsafeRawOp i) {
+        if (i.base() instanceof ArithmeticOp) {
+            // if the base is an arithmetic op, try reducing
+            ArithmeticOp root = (ArithmeticOp) i.base();
+            if (!root.isLive() && root.opcode == LADD) {
+                // match unsafe(x + y) if the x + y is not pinned
+                // try reducing (x + y) and (y + x)
+                Value y = root.y();
+                Value x = root.x();
+                if (reduceRawOp(i, x, y) || reduceRawOp(i, y, x)) {
+                    // the operation was reduced
+                    return;
+                }
+                if (y instanceof Convert) {
+                    // match unsafe(x + (long) y)
+                    Convert convert = (Convert) y;
+                    if (convert.opcode == I2L && convert.value().kind.isInt()) {
+                        // the conversion is redundant
+                        setUnsafeRawOp(i, x, convert.value(), 0);
+                    }
+                }
+            }
+        }
+    }
+
+    private boolean reduceRawOp(UnsafeRawOp i, Value base, Value index) {
+        if (index instanceof Convert) {
+            // skip any conversion operations
+            index = ((Convert) index).value();
+        }
+        if (index instanceof ShiftOp) {
+            // try to match the index as a shift by a constant
+            ShiftOp shift = (ShiftOp) index;
+            CiKind st = shift.y().kind;
+            if (shift.y().isConstant() && st.isInt()) {
+                int val = shift.y().asConstant().asInt();
+                switch (val) {
+                    case 0: // fall through
+                    case 1: // fall through
+                    case 2: // fall through
+                    case 3: return setUnsafeRawOp(i, base, shift.x(), val);
+                }
+            }
+        }
+        if (index instanceof ArithmeticOp) {
+            // try to match the index as a multiply by a constant
+            // note that this case will not happen if C1XOptions.CanonicalizeMultipliesToShifts is true
+            ArithmeticOp arith = (ArithmeticOp) index;
+            CiKind st = arith.y().kind;
+            if (arith.opcode == IMUL && arith.y().isConstant() && st.isInt()) {
+                int val = arith.y().asConstant().asInt();
+                switch (val) {
+                    case 1: return setUnsafeRawOp(i, base, arith.x(), 0);
+                    case 2: return setUnsafeRawOp(i, base, arith.x(), 1);
+                    case 4: return setUnsafeRawOp(i, base, arith.x(), 2);
+                    case 8: return setUnsafeRawOp(i, base, arith.x(), 3);
+                }
+            }
+        }
+
+        return false;
+    }
+
+    private boolean setUnsafeRawOp(UnsafeRawOp i, Value base, Value index, int log2scale) {
+        i.setBase(base);
+        i.setIndex(index);
+        i.setLog2Scale(log2scale);
+        return true;
+    }
+
+    @Override
+    public void visitUnsafeGetRaw(UnsafeGetRaw i) {
+        if (C1XOptions.CanonicalizeUnsafes) {
+            visitUnsafeRawOp(i);
+        }
+    }
+
+    @Override
+    public void visitUnsafePutRaw(UnsafePutRaw i) {
+        if (C1XOptions.CanonicalizeUnsafes) {
+            visitUnsafeRawOp(i);
+        }
+    }
+
+    private Object argAsObject(Value[] args, int index) {
+        CiConstant c = args[index].asConstant();
+        if (c != null) {
+            return runtime.asJavaObject(c);
+        }
+        return null;
+    }
+
+    private Class<?> argAsClass(Value[] args, int index) {
+        CiConstant c = args[index].asConstant();
+        if (c != null) {
+            return runtime.asJavaClass(c);
+        }
+        return null;
+    }
+
+    private double argAsDouble(Value[] args, int index) {
+        return args[index].asConstant().asDouble();
+    }
+
+    private float argAsFloat(Value[] args, int index) {
+        return args[index].asConstant().asFloat();
+    }
+
+    private int argAsInt(Value[] args, int index) {
+        return args[index].asConstant().asInt();
+    }
+
+    private long argAsLong(Value[] args, int index) {
+        return args[index].asConstant().asLong();
+    }
+
+    public static CiConstant foldInvocation(RiRuntime runtime, RiMethod method, final Value[] args) {
+        CiConstant result = runtime.invoke(method, new CiMethodInvokeArguments() {
+            int i;
+            @Override
+            public CiConstant nextArg() {
+                if (i >= args.length) {
+                    return null;
+                }
+                Value arg = args[i++];
+                if (arg == null) {
+                    if (i >= args.length) {
+                        return null;
+                    }
+                    arg = args[i++];
+                    assert arg != null;
+                }
+                return arg.isConstant() ? arg.asConstant() : null;
+            }
+        });
+        if (result != null) {
+            C1XMetrics.MethodsFolded++;
+        }
+        return result;
+    }
+
+    @Override
+    public void visitTypeEqualityCheck(TypeEqualityCheck i) {
+        if (i.condition == Condition.EQ && i.left() == i.right()) {
+            setCanonical(null);
+        }
+    }
+
+    @Override
+    public void visitBoundsCheck(BoundsCheck b) {
+        Value index = b.index();
+        Value length = b.length();
+
+        if (index.isConstant() && length.isConstant()) {
+            int i = index.asConstant().asInt();
+            int l = index.asConstant().asInt();
+            Condition c = b.condition;
+            if (c.check(i, l)) {
+                setCanonical(null);
+            }
+        }
+    }
+
+    private RiType getTypeOf(Value x) {
+        if (x.isConstant()) {
+            return runtime.getTypeOf(x.asConstant());
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/opt/GlobalValueNumberer.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,98 @@
+/*
+ * 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.sun.c1x.opt;
+
+import java.util.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.graph.*;
+import com.sun.c1x.ir.*;
+
+/**
+ * Implements global value numbering based on dominators.
+ *
+ * @author Ben L. Titzer
+ */
+public class GlobalValueNumberer {
+
+    final IR ir;
+    final HashMap<BlockBegin, ValueMap> valueMaps;
+    final InstructionSubstituter subst;
+    ValueMap currentMap;
+
+    /**
+     * Creates a new GlobalValueNumbering pass and performs it on the IR.
+     *
+     * @param ir the IR on which to perform global value numbering
+     */
+    public GlobalValueNumberer(IR ir) {
+        this.ir = ir;
+        this.subst = new InstructionSubstituter(ir);
+        List<BlockBegin> blocks = ir.linearScanOrder();
+        valueMaps = new HashMap<BlockBegin, ValueMap>(blocks.size());
+        optimize(blocks);
+        subst.finish();
+    }
+
+    void optimize(List<BlockBegin> blocks) {
+        int numBlocks = blocks.size();
+        BlockBegin startBlock = blocks.get(0);
+        assert startBlock == ir.startBlock && startBlock.numberOfPreds() == 0 && startBlock.dominator() == null : "start block incorrect";
+
+        // initial value map, with nesting 0
+        valueMaps.put(startBlock, new ValueMap());
+
+        for (int i = 1; i < numBlocks; i++) {
+            // iterate through all the blocks
+            BlockBegin block = blocks.get(i);
+
+            int numPreds = block.numberOfPreds();
+            assert numPreds > 0 : "block must have predecessors";
+
+            BlockBegin dominator = block.dominator();
+            assert dominator != null : "dominator must exist";
+            assert valueMaps.get(dominator) != null : "value map of dominator must exist";
+
+            // create new value map with increased nesting
+            currentMap = new ValueMap(valueMaps.get(dominator));
+
+            assert numPreds > 1 || dominator == block.predAt(0) || block.isExceptionEntry() : "dominator must be equal to predecessor";
+
+            // visit all instructions of this block
+            for (Instruction instr = block.next(); instr != null; instr = instr.next()) {
+                assert !instr.hasSubst() : "substitution already set";
+
+                // attempt value numbering
+                Instruction f = currentMap.findInsert(instr);
+                if (f != instr) {
+                    C1XMetrics.GlobalValueNumberHits++;
+                    assert !subst.hasSubst(f) : "can't have a substitution";
+                    subst.setSubst(instr, f);
+                }
+            }
+
+            // remember value map for successors
+            valueMaps.put(block, currentMap);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/opt/InstructionSubstituter.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,99 @@
+/*
+ * 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.sun.c1x.opt;
+
+import com.sun.c1x.ir.*;
+import com.sun.c1x.value.*;
+import com.sun.c1x.graph.IR;
+
+/**
+ * This class allows instructions to be substituted within an IR graph. It allows
+ * registering substitutions and iterates over the instructions of a program and replaces
+ * the occurrence of each instruction with its substitution, if it has one.
+ *
+ * @author Ben L. Titzer
+ */
+public final class InstructionSubstituter implements BlockClosure, ValueClosure {
+
+    final IR ir;
+    boolean hasSubstitution;
+
+    public InstructionSubstituter(IR ir) {
+        this.ir = ir;
+    }
+
+    public void apply(BlockBegin block) {
+        Instruction last = null;
+        if (block.exceptionHandlerStates() != null) {
+            for (FrameState s : block.exceptionHandlerStates()) {
+                s.valuesDo(this);
+            }
+        }
+        for (Instruction n = block; n != null; n = last.next()) {
+            n.allValuesDo(this);
+            if (n.subst != null && last != null) {
+                // this instruction has a substitution, skip it
+                last.resetNext(n.next());
+            } else {
+                last = n;
+            }
+        }
+    }
+
+    public void finish() {
+        if (hasSubstitution) {
+            ir.startBlock.iterateAnyOrder(this, false);
+        }
+    }
+
+    public boolean hasSubst(Value i) {
+        return i.subst != null;
+    }
+
+    public void setSubst(Value i, Value n) {
+        if (i == n) {
+            i.subst = null;
+        } else {
+            hasSubstitution = true;
+            i.subst = n;
+        }
+    }
+
+    public Value getSubst(Value i) {
+        Value p = i;
+        while (true) {
+            if (p.subst == null) {
+                break;
+            }
+            p = p.subst;
+        }
+        return p;
+    }
+
+    public Value apply(Value i) {
+        if (i != null) {
+            return getSubst(i);
+        }
+        return i;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/opt/LivenessMarker.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,199 @@
+/*
+ * 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.sun.c1x.opt;
+
+import static com.sun.c1x.ir.Value.Flag.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.graph.*;
+import com.sun.c1x.ir.*;
+import com.sun.c1x.value.*;
+
+/**
+ * The {@code LivenessMarker} class walks over an IR graph and marks instructions
+ * whose values are live, either because they are needed to compute the method's result,
+ * may produce a side-effect, or are needed for deoptimization.
+ *
+ * @author Ben L. Titzer
+ */
+public final class LivenessMarker {
+
+    final IR ir;
+
+    final InstructionMarker deoptMarker = new InstructionMarker(LiveDeopt);
+    final InstructionMarker valueMarker = new InstructionMarker(LiveValue);
+
+    int count;
+
+    /**
+     * Creates a new liveness marking instance and marks live instructions.
+     * @param ir the IR to mark
+     */
+    public LivenessMarker(IR ir) {
+        this.ir = ir;
+        markRoots();
+    }
+
+    private void markRoots() {
+        // first pass: mark root instructions and their inputs
+        ir.startBlock.iteratePreOrder(new BlockClosure() {
+            public void apply(BlockBegin block) {
+                block.stateBefore().valuesDo(deoptMarker);
+                if (block.stateAfter() != null) {
+                    block.stateAfter().valuesDo(deoptMarker);
+                }
+                Instruction i = block;
+                while ((i = i.next()) != null) {
+                    // visit all instructions first, marking control dependent and side-effects
+                    markRootInstr(i);
+                }
+            }
+        });
+
+        // propagate liveness flags to inputs of instructions
+        valueMarker.markAll();
+        deoptMarker.markAll();
+    }
+
+    public int liveCount() {
+        return count;
+    }
+
+    public void removeDeadCode() {
+        // second pass: remove dead instructions from blocks
+        ir.startBlock.iteratePreOrder(new BlockClosure() {
+            public void apply(BlockBegin block) {
+                Instruction prev = block;
+                Instruction i = block.next();
+                while (i != null) {
+                    if (i.isLive()) {
+                        prev.resetNext(i); // skip any previous dead instructions
+                        prev = i;
+                    } else {
+                        C1XMetrics.DeadCodeEliminated++;
+                    }
+                    i = i.next();
+                }
+            }
+        });
+        // clear all marks on all instructions
+        valueMarker.clearAll();
+        deoptMarker.clearAll();
+    }
+
+    private static class Link {
+        final Value value;
+        Link next;
+
+        Link(Value v) {
+            this.value = v;
+        }
+    }
+
+    private final class InstructionMarker implements ValueClosure {
+        final Value.Flag reason;
+        Link head;
+        Link tail;
+
+        public InstructionMarker(Value.Flag reason) {
+            this.reason = reason;
+        }
+
+        public Value apply(Value i) {
+            if (!i.checkFlag(reason) && !i.isDeadPhi()) {
+                // set the flag and add to the queue
+                setFlag(i, reason);
+                if (head == null) {
+                    head = tail = new Link(i);
+                } else {
+                    tail.next = new Link(i);
+                    tail = tail.next;
+                }
+            }
+            return i;
+        }
+
+        private void markAll() {
+            Link cursor = head;
+            while (cursor != null) {
+                markInputs(cursor.value);
+                cursor = cursor.next;
+            }
+        }
+
+        private void clearAll() {
+            Link cursor = head;
+            while (cursor != null) {
+                cursor.value.clearLive();
+                cursor = cursor.next;
+            }
+        }
+
+        private void markInputs(Value i) {
+            if (!i.isDeadPhi()) {
+                i.inputValuesDo(this);
+                if (i instanceof Phi) {
+                    // phis are special
+                    Phi phi = (Phi) i;
+                    int max = phi.inputCount();
+                    for (int j = 0; j < max; j++) {
+                        apply(phi.inputAt(j));
+                    }
+                }
+            }
+        }
+    }
+
+    void markRootInstr(Instruction i) {
+        FrameState stateBefore = i.stateBefore();
+        if (stateBefore != null) {
+            // stateBefore != null implies that this instruction may have side effects
+            stateBefore.valuesDo(deoptMarker);
+            i.inputValuesDo(valueMarker);
+            setFlag(i, LiveSideEffect);
+        } else if (i.checkFlag(LiveStore)) {
+            // instruction is a store that cannot be eliminated
+            i.inputValuesDo(valueMarker);
+            setFlag(i, LiveSideEffect);
+        } else if (i.checkFlag(LiveSideEffect)) {
+            // instruction has a side effect
+            i.inputValuesDo(valueMarker);
+        }
+        if (i instanceof BlockEnd) {
+            // input values to block ends are control dependencies
+            i.inputValuesDo(valueMarker);
+            setFlag(i, LiveControl);
+        }
+        FrameState stateAfter = i.stateAfter();
+        if (stateAfter != null) {
+            stateAfter.valuesDo(deoptMarker);
+        }
+    }
+
+    void setFlag(Value i, Value.Flag flag) {
+        if (!i.isLive()) {
+            count++;
+        }
+        i.setFlag(flag);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/opt/NullCheckEliminator.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,599 @@
+/*
+ * 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.sun.c1x.opt;
+
+import java.util.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.graph.*;
+import com.sun.c1x.ir.*;
+import com.sun.c1x.util.*;
+import com.sun.c1x.value.FrameState.*;
+import com.sun.cri.ci.*;
+
+/**
+ * This class implements a data-flow analysis to remove redundant null checks
+ * and deoptimization info for instructions that cannot ever produce {@code NullPointerException}s.
+ *
+ * This implementation uses an optimistic dataflow analysis by attempting to visit all predecessors
+ * of a block before visiting the block itself. For this purpose it uses the block numbers computed by
+ * the {@link BlockMap} during graph construction, which may not actually be
+ * a valid reverse post-order number (due to inlining and any previous optimizations).
+ *
+ * When loops are encountered, or if the blocks are not visited in the optimal order, this implementation
+ * will fall back to performing an iterative data flow analysis where it maintains a set
+ * of incoming non-null instructions and a set of locally produced outgoing non-null instructions
+ * and iterates the dataflow equations to a fixed point. Basically, for block b,
+ * out(b) = in(b) U local_out(b) and in(b) = intersect(out(pred)). After a fixed point is
+ * reached, the resulting incoming sets are used to visit instructions with uneliminated null checks
+ * a second time.
+ *
+ * Note that the iterative phase is actually optional, because the first pass is conservative.
+ * Iteration can be disabled by setting {@link C1XOptions#OptIterativeNCE} to
+ * {@code false}. Iteration is rarely necessary for acyclic graphs.
+ *
+ * @author Ben L. Titzer
+ */
+public class NullCheckEliminator extends DefaultValueVisitor {
+
+    private static class IfEdge {
+        final BlockBegin ifBlock;
+        final BlockBegin succ;
+        final Value checked;
+
+        IfEdge(BlockBegin i, BlockBegin s, Value c) {
+            this.ifBlock = i;
+            this.succ = s;
+            this.checked = c;
+        }
+    }
+
+    private static class BlockInfo {
+        // used in first pass
+        final BlockBegin block;
+        boolean marked;
+        CiBitMap localOut;
+        CiBitMap localExcept;
+        List<Value> localUses;
+        // used in iteration and flow sensitivity
+        IfEdge ifEdge;
+        CiBitMap localIn;
+
+        BlockInfo(BlockBegin b) {
+            this.block = b;
+        }
+    }
+
+    private static class ValueInfo {
+        final Value value;
+        final int globalIndex;
+
+        ValueInfo(Value value, int index) {
+            this.value = value;
+            globalIndex = index;
+        }
+    }
+
+    final IR ir;
+    final BlockWorkList workList = new BlockWorkList();
+
+    final ArrayList<BlockInfo> blockInfos = new ArrayList<BlockInfo>(5);
+    final ArrayList<ValueInfo> valueInfos = new ArrayList<ValueInfo>(5);
+    final ArrayList<BlockInfo> remainingUses = new ArrayList<BlockInfo>(5);
+
+    // maps used only in iteration
+    boolean requiresIteration;
+    int maximumIndex;
+
+    CiBitMap currentBitMap;
+    List<Value> currentUses;
+
+    /**
+     * Creates a new null check eliminator for the specified IR and performs the optimization.
+     * @param ir the IR
+     */
+    public NullCheckEliminator(IR ir) {
+        this.ir = ir;
+        optimize();
+    }
+
+    private void optimize() {
+        if (C1XOptions.PrintTimers) {
+            C1XTimers.NCE.start();
+        }
+        BlockInfo start = getBlockInfo(ir.startBlock);
+        mark(start);
+        processBlock(start);
+        while (!workList.isEmpty()) {
+            processBlock(getBlockInfo(workList.removeFromWorkList()));
+        }
+        if (requiresIteration && C1XOptions.OptIterativeNCE) {
+            // there was a loop, or blocks were not visited in reverse post-order;
+            // iteration is required to compute the in sets for a second pass
+            iterate();
+        }
+        clearInfo();
+        if (C1XOptions.PrintTimers) {
+            C1XTimers.NCE.stop();
+        }
+    }
+
+    private void processBlock(BlockInfo info) {
+        BlockBegin block = info.block;
+        // first pass on a block
+        computeLocalInSet(info);
+        // process any phis in the block
+        block.stateBefore().forEachPhi(block, new PhiProcedure() {
+            public boolean doPhi(Phi phi) {
+                visitPhi(phi);
+                return true;
+            }
+        });
+
+        // now visit the instructions in order
+        for (Instruction i = block.next(); i != null; i = i.next()) {
+            i.accept(this);
+        }
+        if (!currentUses.isEmpty()) {
+            // remember any localUses in this block for later iterative processing
+            info.localUses = currentUses;
+            remainingUses.add(info);
+        }
+        queueSuccessors(block.end().successors());
+        queueSuccessors(block.exceptionHandlerBlocks());
+    }
+
+    private void queueSuccessors(List<BlockBegin> successorList) {
+        for (BlockBegin succ : successorList) {
+            BlockInfo info = getBlockInfo(succ);
+            if (!isMarked(info)) {
+                workList.addSorted(succ, succ.depthFirstNumber());
+                mark(info);
+            }
+        }
+    }
+
+    private void computeLocalInSet(BlockInfo info) {
+        BlockBegin block = info.block;
+        // compute the initial {in} set based on the {localOut} sets of predecessors, if possible
+        currentBitMap = null;
+        currentUses = new ArrayList<Value>();
+        if (block.numberOfPreds() == 0) {
+            // no predecessors => start block
+            assert block == ir.startBlock : "block without predecessors should be start block";
+            currentBitMap = newBitMap();
+        } else {
+            // block has at least one predecessor
+            for (BlockBegin pred : block.predecessors()) {
+                if (getPredecessorMap(pred, block.isExceptionEntry()) == null) {
+                    // one of the predecessors of this block has not been visited,
+                    // we have to be conservative and start with nothing known
+                    currentBitMap = newBitMap();
+                    requiresIteration = true;
+                }
+            }
+            if (currentBitMap == null) {
+                // all the predecessors have been visited, compute the intersection of their {localOut} sets
+                for (BlockBegin pred : block.predecessors()) {
+                    BlockInfo predInfo = getBlockInfo(pred);
+                    CiBitMap predMap = getPredecessorMap(predInfo, block.isExceptionEntry());
+                    currentBitMap = intersectLocalOut(predInfo, currentBitMap, predMap, block);
+                }
+            }
+        }
+        assert currentBitMap != null : "current bitmap should be computed one or the other way";
+        // if there are exception handlers for this block, then clone {in} and put it in {localExcept}
+        if (block.numberOfExceptionHandlers() > 0) {
+            info.localExcept = currentBitMap.copy();
+        }
+        info.localOut = currentBitMap;
+    }
+
+    private CiBitMap intersectLocalOut(BlockInfo pred, CiBitMap current, CiBitMap predMap, BlockBegin succ) {
+        predMap = intersectFlowSensitive(pred, predMap, succ);
+        if (current == null) {
+            current = predMap.copy();
+        } else {
+            current.setIntersect(predMap);
+        }
+        return current;
+    }
+
+    private CiBitMap intersectFlowSensitive(BlockInfo pred, CiBitMap n, BlockBegin succ) {
+        if (C1XOptions.OptFlowSensitiveNCE) {
+            // check to see if there is an if edge between these two blocks
+            if (pred.ifEdge != null && pred.ifEdge.succ == succ) {
+                // if there is a special edge between pred and block, add the checked instruction
+                n = n.copy();
+                setValue(pred.ifEdge.checked, n);
+            }
+        }
+        return n;
+    }
+
+    private void iterate() {
+        // the previous phase calculated all the {localOut} sets; use iteration to
+        // calculate the {in} sets
+        if (remainingUses.size() > 0) {
+            // only perform iterative flow analysis if there are checks remaining to eliminate
+            C1XMetrics.NullCheckIterations++;
+            clearMarked();
+            // start off by propagating a new set to the start block
+            propagate(getBlockInfo(ir.startBlock), newBitMap(), ir.startBlock);
+            while (!workList.isEmpty()) {
+                BlockInfo block = getBlockInfo(workList.removeFromWorkList());
+                unmark(block);
+                iterateBlock(block);
+            }
+            // now that the fixed point is reached, reprocess any remaining localUses
+            currentUses = null; // the list won't be needed this time
+            for (BlockInfo info : remainingUses) {
+                reprocessUses(info.localIn, info.localUses);
+            }
+        }
+    }
+
+    private void iterateBlock(BlockInfo info) {
+        CiBitMap prevMap = info.localIn;
+        assert prevMap != null : "how did the block get on the worklist without an initial in map?";
+        CiBitMap localOut = info.localOut;
+        CiBitMap out;
+        // copy larger and do union with smaller
+        if (localOut.size() > prevMap.size()) {
+            out = localOut.copy();
+            out.setUnion(prevMap);
+        } else {
+            out = prevMap.copy();
+            out.setUnion(localOut);
+        }
+        propagateSuccessors(info, out, info.block.end().successors()); // propagate {in} U {localOut} to successors
+        propagateSuccessors(info, prevMap, info.block.exceptionHandlerBlocks()); // propagate {in} to exception handlers
+    }
+
+    private void propagateSuccessors(BlockInfo block, CiBitMap out, List<BlockBegin> successorList) {
+        for (BlockBegin succ : successorList) {
+            propagate(block, out, succ);
+        }
+    }
+
+    private void propagate(BlockInfo pred, CiBitMap bitMap, BlockBegin succ) {
+        boolean changed;
+        BlockInfo succInfo = getBlockInfo(succ);
+        if (succInfo.localIn == null) {
+            // this is the first time this block is being iterated
+            succInfo.localIn = bitMap.copy();
+            propagateFlowSensitive(pred, succInfo.localIn, succ, false);
+            changed = true;
+        } else {
+            // perform intersection with previous map
+            bitMap = propagateFlowSensitive(pred, bitMap, succ, true);
+            changed = succInfo.localIn.setIntersect(bitMap);
+        }
+        if (changed && !isMarked(succInfo)) {
+            mark(succInfo);
+            workList.addSorted(succ, succ.depthFirstNumber());
+        }
+    }
+
+    private CiBitMap propagateFlowSensitive(BlockInfo pred, CiBitMap bitMap, BlockBegin succ, boolean copy) {
+        if (C1XOptions.OptFlowSensitiveNCE) {
+            if (pred.ifEdge != null && pred.ifEdge.succ == succ) {
+                if (copy) {
+                    bitMap = bitMap.copy();
+                }
+                // there is a special if edge between these blocks, add the checked instruction
+                setValue(pred.ifEdge.checked, bitMap);
+            }
+        }
+        return bitMap;
+    }
+
+    private void reprocessUses(CiBitMap in, List<Value> uses) {
+        // iterate over each of the use instructions again, using the input bitmap
+        // and the hash sets
+        assert in != null;
+        currentBitMap = in;
+        for (Value i : uses) {
+            i.accept(this);
+        }
+    }
+
+    private boolean processUse(Value use, Value object, boolean implicitCheck) {
+        if (object.isNonNull()) {
+            // the object itself is known for sure to be non-null, so clear the flag.
+            // the flag is usually cleared in the constructor of the using instruction, but
+            // later optimizations may more reveal more non-null objects
+            use.eliminateNullCheck();
+            return true;
+        } else {
+            // check if the object is non-null in the bitmap or hashset
+            if (checkValue(object, currentBitMap)) {
+                // the object is non-null at this site
+                use.eliminateNullCheck();
+                return true;
+            } else {
+                if (implicitCheck) {
+                    // the object will be non-null after executing this instruction
+                    setValue(object, currentBitMap);
+                }
+                if (currentUses != null) {
+                    currentUses.add(use); // record a use for potential later iteration
+                }
+            }
+        }
+        return false;
+    }
+
+    private boolean isNonNullOnEdge(BlockBegin pred, BlockBegin succ, Value i) {
+        if (C1XOptions.OptFlowSensitiveNCE) {
+            IfEdge e = getBlockInfo(pred).ifEdge;
+            if (e != null && e.succ == succ && e.checked == i) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public void visitPhi(Phi phi) {
+        for (int j = 0; j < phi.inputCount(); j++) {
+            Value operand = phi.inputAt(j);
+            if (processUse(phi, operand, false)) {
+                continue;
+            }
+            if (C1XOptions.OptFlowSensitiveNCE) {
+                BlockBegin phiBlock = phi.block();
+                if (!phiBlock.isExceptionEntry() && isNonNullOnEdge(phiBlock.predecessors().get(j), phiBlock, operand)) {
+                    continue;
+                }
+            }
+            return;
+        }
+        // all inputs are non-null
+        phi.setFlag(Value.Flag.NonNull);
+    }
+
+    @Override
+    public void visitLoadPointer(LoadPointer i) {
+        Value pointer = i.pointer();
+        if (pointer != null) {
+            processUse(i, pointer, true);
+        }
+    }
+
+    @Override
+    public void visitUnsafeCast(UnsafeCast i) {
+        if (processUse(i, i.value(), false)) {
+            // if the object is non null, the result of the cast is as well
+            i.setFlag(Value.Flag.NonNull);
+        }
+    }
+
+    @Override
+    public void visitLoadField(LoadField i) {
+        Value object = i.object();
+        if (object != null) {
+            processUse(i, object, true);
+        }
+    }
+
+    @Override
+    public void visitStorePointer(StorePointer i) {
+        Value pointer = i.pointer();
+        if (pointer != null) {
+            processUse(i, pointer, true);
+        }
+    }
+
+    @Override
+    public void visitStoreField(StoreField i) {
+        Value object = i.object();
+        if (object != null) {
+            processUse(i, object, true);
+        }
+    }
+
+    @Override
+    public void visitArrayLength(ArrayLength i) {
+        processUse(i, i.array(), true);
+    }
+
+    @Override
+    public void visitLoadIndexed(LoadIndexed i) {
+        processUse(i, i.array(), true);
+    }
+
+    @Override
+    public void visitStoreIndexed(StoreIndexed i) {
+        processUse(i, i.array(), true);
+    }
+
+    @Override
+    public void visitNullCheck(NullCheck i) {
+        processUse(i, i.object(), true);
+    }
+
+    @Override
+    public void visitInvoke(Invoke i) {
+        if (!i.isStatic()) {
+            processUse(i, i.receiver(), true);
+        }
+    }
+
+    @Override
+    public void visitCheckCast(CheckCast i) {
+        if (processUse(i, i.object(), false)) {
+            // if the object is non null, the result of the cast is as well
+            i.setFlag(Value.Flag.NonNull);
+        }
+    }
+
+    @Override
+    public void visitInstanceOf(InstanceOf i) {
+        processUse(i, i.object(), false); // instanceof can check faster if object is non-null
+    }
+
+    @Override
+    public void visitMonitorEnter(MonitorEnter i) {
+        processUse(i, i.object(), true);
+    }
+
+    @Override
+    public void visitIntrinsic(Intrinsic i) {
+        if (!i.isStatic()) {
+            processUse(i, i.receiver(), true);
+        }
+    }
+
+    @Override
+    public void visitIf(If i) {
+        if (C1XOptions.OptFlowSensitiveNCE) {
+            if (i.trueSuccessor() != i.falseSuccessor()) {
+                // if the two successors are different, then we may learn something on one branch
+                Value x = i.x();
+                if (x.kind == CiKind.Object) {
+                    // this is a comparison of object references
+                    Value y = i.y();
+                    if (processUse(i, x, false)) {
+                        // x is known to be non-null
+                        compareAgainstNonNull(i, y);
+                    } else if (processUse(i, y, false)) {
+                        // y is known to be non-null
+                        compareAgainstNonNull(i, x);
+                    } else if (x.isNullConstant()) {
+                        // x is the null constant
+                        compareAgainstNull(i, y);
+                    } else if (y.isNullConstant()) {
+                        // y is the null constaint
+                        compareAgainstNull(i, x);
+                    }
+                }
+                // XXX: also check (x instanceof T) tests
+            }
+        }
+    }
+
+    private void compareAgainstNonNull(If i, Value use) {
+        if (i.condition() == Condition.EQ) {
+            propagateNonNull(i, use, i.trueSuccessor());
+        }
+    }
+
+    private void compareAgainstNull(If i, Value use) {
+        if (i.condition() == Condition.EQ) {
+            propagateNonNull(i, use, i.falseSuccessor());
+        } else if (i.condition() == Condition.NE) {
+            propagateNonNull(i, use, i.trueSuccessor());
+        }
+    }
+
+    private void propagateNonNull(If i, Value use, BlockBegin succ) {
+        BlockInfo info = getBlockInfo(i.begin());
+        if (info.ifEdge == null) {
+            // Only use one if edge.
+            info.ifEdge = new IfEdge(i.begin(), succ, use);
+        }
+    }
+
+    private ValueInfo getValueInfo(Value value) {
+        Object info = value.optInfo;
+        if (info instanceof ValueInfo) {
+            return (ValueInfo) info;
+        }
+        C1XMetrics.NullCheckIdsAssigned++;
+        ValueInfo ninfo = new ValueInfo(value, maximumIndex++);
+        value.optInfo = ninfo;
+        valueInfos.add(ninfo);
+        return ninfo;
+    }
+
+    private BlockInfo getBlockInfo(BlockBegin block) {
+        Object info = block.optInfo;
+        if (info instanceof BlockInfo) {
+            return (BlockInfo) info;
+        }
+        BlockInfo ninfo = new BlockInfo(block);
+        block.optInfo = ninfo;
+        blockInfos.add(ninfo);
+        return ninfo;
+    }
+
+    private void setValue(Value value, CiBitMap bitmap) {
+        int index = getValueInfo(value).globalIndex;
+        bitmap.grow(index + 1);
+        bitmap.set(index);
+        if (value instanceof UnsafeCast) {
+            // An unsafe cast is just an alias
+            setValue(((UnsafeCast) value).value(), bitmap);
+        }
+    }
+
+    private boolean checkValue(Value value, CiBitMap bitmap) {
+        Object info = value.optInfo;
+        return info instanceof ValueInfo && bitmap.getDefault(((ValueInfo) info).globalIndex);
+    }
+
+    private boolean isMarked(BlockInfo block) {
+        return block.marked;
+    }
+
+    private void mark(BlockInfo block) {
+        block.marked = true;
+    }
+
+    private void unmark(BlockInfo block) {
+        block.marked = false;
+    }
+
+    private void clearInfo() {
+        // be a good citizen and clear all the information added to nodes
+        // (also avoids confusing a later application of this same optimization)
+        for (BlockInfo info : blockInfos) {
+            assert info.block.optInfo instanceof BlockInfo : "inconsistent block information";
+            info.block.optInfo = null;
+        }
+        for (ValueInfo info : valueInfos) {
+            assert info.value.optInfo instanceof ValueInfo : "inconsistent value information";
+            info.value.optInfo = null;
+        }
+    }
+
+    private void clearMarked() {
+        for (BlockInfo info : blockInfos) {
+            info.marked = false;
+        }
+    }
+
+    private CiBitMap newBitMap() {
+        return new CiBitMap(maximumIndex > 32 ? maximumIndex : 32);
+    }
+
+    private CiBitMap getPredecessorMap(BlockBegin pred, boolean exceptionBlock) {
+        BlockInfo predInfo = getBlockInfo(pred);
+        return exceptionBlock ? predInfo.localExcept : predInfo.localOut;
+    }
+
+    private CiBitMap getPredecessorMap(BlockInfo predInfo, boolean exceptionBlock) {
+        return exceptionBlock ? predInfo.localExcept : predInfo.localOut;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/opt/PhiSimplifier.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,128 @@
+/*
+ * 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.sun.c1x.opt;
+
+import com.sun.c1x.graph.IR;
+import com.sun.c1x.ir.*;
+import com.sun.c1x.value.*;
+
+/**
+ * The {@code PhiSimplifier} class is a helper class that can reduce phi instructions.
+ *
+ * @author Ben L. Titzer
+ */
+public final class PhiSimplifier implements BlockClosure {
+
+    final IR ir;
+    final InstructionSubstituter subst;
+
+    public PhiSimplifier(IR ir) {
+        this.ir = ir;
+        this.subst = new InstructionSubstituter(ir);
+        ir.startBlock.iterateAnyOrder(this, false);
+        subst.finish();
+    }
+
+    /**
+     * This method is called for each block and processes any phi statements in the block.
+     * @param block the block to apply the simplification to
+     */
+    public void apply(BlockBegin block) {
+        FrameState state = block.stateBefore();
+        for (int i = 0; i < state.stackSize(); i++) {
+            simplify(state.stackAt(i));
+        }
+        for (int i = 0; i < state.localsSize(); i++) {
+            simplify(state.localAt(i));
+        }
+    }
+
+    Value simplify(Value x) {
+        if (x == null || !(x instanceof Phi)) {
+            return x;
+        }
+        Phi phi = (Phi) x;
+        if (phi.hasSubst()) {
+            // already substituted, but the subst could be a phi itself, so simplify
+            return simplify(subst.getSubst(phi));
+        } else if (phi.checkFlag(Value.Flag.PhiCannotSimplify)) {
+            // already tried, cannot simplify this phi
+            return phi;
+        } else if (phi.checkFlag(Value.Flag.PhiVisited)) {
+            // break cycles in phis
+            return phi;
+        } else if (phi.isIllegal()) {
+            // don't bother with illegals
+            return phi;
+        } else {
+            // attempt to simplify the phi by recursively simplifying its operands
+            phi.setFlag(Value.Flag.PhiVisited);
+            Value phiSubst = null;
+            int max = phi.inputCount();
+            boolean cannotSimplify = false;
+            for (int i = 0; i < max; i++) {
+                Value oldInstr = phi.inputAt(i);
+
+                if (oldInstr == null || oldInstr.isIllegal() || oldInstr.isDeadPhi()) {
+                    // if one operand is illegal, make the entire phi illegal
+                    phi.makeDead();
+                    phi.clearFlag(Value.Flag.PhiVisited);
+                    return phi;
+                }
+
+                Value newInstr = simplify(oldInstr);
+
+                if (newInstr == null || newInstr.isIllegal() || newInstr.isDeadPhi()) {
+                    // if the subst instruction is illegal, make the entire phi illegal
+                    phi.makeDead();
+                    phi.clearFlag(Value.Flag.PhiVisited);
+                    return phi;
+                }
+
+                // 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) {
+                phi.setFlag(Value.Flag.PhiCannotSimplify);
+                phi.clearFlag(Value.Flag.PhiVisited);
+                return phi;
+            }
+
+            // successfully simplified the phi
+            assert phiSubst != null : "illegal phi function";
+            phi.clearFlag(Value.Flag.PhiVisited);
+            subst.setSubst(phi, phiSubst);
+            return phiSubst;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/opt/SCCPropagator.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,35 @@
+/*
+ * 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.sun.c1x.opt;
+
+/**
+ * The {@code SCCPropagator} class implements sparse conditional constant propagation.
+ * While most canonicalization opportunities are revealed and exploited during graph construction
+ * in SSA form, some opportunities can be missed, and still more may be created by later optimizations.
+ * This class implements a classic iterative data-flow analysis to discover all canonicalization
+ * opportunities.
+ *
+ * @author Ben L. Titzer
+ */
+public class SCCPropagator {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/opt/TypeAnalyzer.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.opt;
+
+import com.sun.c1x.graph.IR;
+import com.sun.cri.ri.*;
+
+/**
+ * This class implements an iterative, flow-sensitve type analysis that can be
+ * used to remove redundant checkcasts and instanceof tests as well as devirtualize
+ * and deinterface method calls.
+ *
+ * @author Ben L. Titzer
+ */
+public class TypeAnalyzer {
+
+    final IR ir;
+
+    public TypeAnalyzer(IR ir) {
+        this.ir = ir;
+    }
+
+    // type information sources:
+    // new, anewarray, newarray
+    // parameter types
+    // instanceof
+    // checkcast
+    // array stores
+    // array loads
+    // field loads
+    // exception handler type
+    // equality comparison
+    // call to Object.clone()
+    // call to Class.newInstance()
+    // call to Array.newInstance()
+    // call to Class.isInstance()
+
+    // possible optimizations:
+    // remove redundant checkcasts
+    // fold instanceof tests
+    // remove dead branches in folded instanceof
+    // detect redundant store checks
+    // convert invokeinterface to invokevirtual when possible
+    // convert invokevirtual to invokespecial when possible
+    // remove finalizer checks
+    // specialize array copy calls
+    // transform reflective Class.newInstance() into allocation
+    // transform reflective Array.newInstance() into allocation
+    // transform reflective Class.isInstance() to checkcast
+    // transform reflective method invocation to direct method invocation
+
+    private static class TypeApprox {
+        final RiType type = null;
+        final boolean exact = false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/opt/UnsafeCastEliminator.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,76 @@
+/*
+ * 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.sun.c1x.opt;
+
+import com.sun.c1x.graph.*;
+import com.sun.c1x.ir.*;
+import com.sun.c1x.value.*;
+
+/**
+ * A mechanism to remove {@linkplain UnsafeCast#redundant redundant} unsafe casts.
+ *
+ * @author Doug Simon
+ */
+public class UnsafeCastEliminator implements ValueClosure, BlockClosure {
+
+    final IR ir;
+
+    /**
+     * Eliminates redundant unsafe casts from a given IR.
+     */
+    public UnsafeCastEliminator(IR ir) {
+        this.ir = ir;
+        ir.startBlock.iterateAnyOrder(this, false);
+    }
+
+    public void apply(BlockBegin block) {
+        if (block.isExceptionEntry()) {
+            for (FrameState ehState : block.exceptionHandlerStates()) {
+                ehState.valuesDo(this);
+            }
+        }
+
+        Instruction i = block;
+        while (i != null) {
+            FrameState stateBefore = i.stateBefore();
+            if (stateBefore != null) {
+                stateBefore.valuesDo(this);
+            }
+            i.inputValuesDo(this);
+            FrameState stateAfter = i.stateAfter();
+            if (stateAfter != null) {
+                stateAfter.valuesDo(this);
+            }
+            i = i.next();
+        }
+    }
+
+    public Value apply(Value i) {
+        if (i instanceof UnsafeCast) {
+            Value y = ((UnsafeCast) i).nonRedundantReplacement();
+            assert y != null;
+            return y;
+        }
+        return i;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/opt/ValueMap.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,163 @@
+/*
+ * 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.sun.c1x.opt;
+
+import com.sun.c1x.*;
+import com.sun.c1x.ir.*;
+
+/**
+ * The {@code ValueMap} class implements a nested hashtable data structure
+ * for use in local and global value numbering.
+ *
+ * @author Ben L. Titzer
+ */
+public class ValueMap {
+    /**
+     * The class that forms hash chains.
+     */
+    private static class Link {
+        final ValueMap map;
+        final int valueNumber;
+        final Instruction value;
+        final Link next;
+
+        Link(ValueMap map, int valueNumber, Instruction value, Link next) {
+            this.map = map;
+            this.valueNumber = valueNumber;
+            this.value = value;
+            this.next = next;
+        }
+    }
+
+    private final ValueMap parent;
+
+    /**
+     * The table of links, indexed by hashing using the {@link Instruction#valueNumber() method}.
+     * The hash chains themselves may share parts of the parents' hash chains at the end.
+     */
+    private Link[] table;
+
+    /**
+     * Total number of entries in this map and the parent, used to compute unique ids.
+     */
+    private int count;
+
+    /**
+     * The maximum size allowed before triggering resizing.
+     */
+    private int max;
+
+    /**
+     * Creates a new value map.
+     */
+    public ValueMap() {
+        parent = null;
+        table = new Link[19];
+    }
+
+    /**
+     * Creates a new value map with the specified parent value map.
+     * @param parent the parent value map
+     */
+    public ValueMap(ValueMap parent) {
+        this.parent = parent;
+        this.table = parent.table.clone();
+        this.count = parent.count;
+        this.max = table.length + table.length / 2;
+    }
+
+    /**
+     * Inserts a value into the value map and looks up any previously available value.
+     * @param x the instruction to insert into the value map
+     * @return the value with which to replace the specified instruction, or the specified
+     * instruction if there is no replacement
+     */
+    public Instruction findInsert(Instruction x) {
+        int valueNumber = x.valueNumber();
+        if (valueNumber != 0) {
+            // value number != 0 means the instruction can be value numbered
+            int index = indexOf(valueNumber, table);
+            Link l = table[index];
+            // hash and linear search
+            while (l != null) {
+                if (l.valueNumber == valueNumber && l.value.valueEqual(x)) {
+                    return l.value;
+                }
+                l = l.next;
+            }
+            // not found; insert
+            table[index] = new Link(this, valueNumber, x, table[index]);
+            if (count > max) {
+                resize();
+            }
+        }
+        return x;
+    }
+
+    /**
+     * Kills all values in this local value map.
+     */
+    public void killAll() {
+        assert parent == null : "should only be used for local value numbering";
+        for (int i = 0; i < table.length; i++) {
+            table[i] = null;
+        }
+        count = 0;
+    }
+
+    private void resize() {
+        C1XMetrics.ValueMapResizes++;
+        Link[] ntable = new Link[table.length * 3 + 4];
+        if (parent != null) {
+            // first add all the parent's entries by cloning them
+            for (int i = 0; i < table.length; i++) {
+                Link l = table[i];
+                while (l != null && l.map == this) {
+                    l = l.next; // skip entries in this map
+                }
+                while (l != null) {
+                    // copy entries from parent
+                    int index = indexOf(l.valueNumber, ntable);
+                    ntable[index] = new Link(l.map, l.valueNumber, l.value, ntable[index]);
+                    l = l.next;
+                }
+            }
+        }
+
+        for (int i = 0; i < table.length; i++) {
+            Link l = table[i];
+            // now add all the entries from this map
+            while (l != null && l.map == this) {
+                int index = indexOf(l.valueNumber, ntable);
+                ntable[index] = new Link(l.map, l.valueNumber, l.value, ntable[index]);
+                l = l.next;
+            }
+        }
+        table = ntable;
+        max = table.length + table.length / 2;
+    }
+
+    private int indexOf(int valueNumber, Link[] t) {
+        return (valueNumber & 0x7fffffff) % t.length;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/package-info.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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 C1X containing options, metrics, timers and the main compiler class
+ * {@link com.sun.c1x.C1XCompiler}.
+ *
+ * <H2>{@code C1XCompiler} Overview</H2>
+ *
+ * C1X 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 C1XCompiler}. {@code C1XCompiler} 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 C1X'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 C1X Compilation Process</H3>
+ *
+ * {@link com.sun.c1x.C1XCompiler#compileMethod} creates a {@link C1XCompilation} instance and then returns the result of calling its
+ * {@link com.sun.c1x.C1XCompilation#compile} method. The {@code C1XCompilation} 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 C1XCompiler} instance, there may be several compilations proceeding concurrently, each of
+ * which is represented by a unique {@code C1XCompilation} instance. The static method {@link com.sun.c1x.C1XCompilation#current}} returns the
+ * {@code C1XCompilation} 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 C1XCompilation} 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.sun.c1x.C1XCompilation#emitHIR}, which creates the high-level intermediate representation (HIR) from the
+ * bytecodes of the method. The HIR is managed by the {@link com.sun.c1x.graph.IR} class, an instance of which is created by
+ * {@code emitHR}, which then calls the {{@link com.sun.c1x.graph.IR#build}} method and returns the result. The {@code C1XCompilation} 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 C1X compiler, including future directions,
+ * refactorings, missing features, broken features, etc.
+ *
+ *
+ * <h3>Anticipated Refactorings</h3>
+ *
+ * <ul>
+ * <li>
+ * The HIR nodes {@link com.sun.c1x.ir.UnsafePrefetch}, {@link com.sun.c1x.ir.UnsafePutObject}, etc should be replaced by uses of the newer
+ * {@link com.sun.c1x.ir.LoadPointer} and {@link com.sun.c1x.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.sun.c1x.ir.Info} object for each HIR node, and remove the
+ * {@link com.sun.c1x.ir.Instruction#exceptionHandlers} field, the {@link com.sun.c1x.ir.Instruction#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.sun.c1x.value.FrameStateInfo} for debugging information. The {@link com.sun.c1x.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.sun.c1x.graph.GraphBuilder} 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 C1X 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.sun.c1x.alloc.LinearScan#computeDebugInfo} method. To complete this metadata, the
+ * {@link com.sun.c1x.alloc.LinearScan} class must implement the {@link ValueLocator} interface and pass it to the
+ * {@link com.sun.c1x.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.sun.c1x.target.amd64.AMD64Backend}, {@link com.sun.c1x.target.amd64.AMD64LIRGenerator}, {@link com.sun.c1x.target.amd64.AMD64LIRAssembler}, etc).</li>
+ *
+ * <li>
+ * XIR for safepoints. The C1X 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 C1X 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 C1X 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. C1X 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.sun.c1x.C1XIntrinsic 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.sun.c1x.C1XOptions#OptIntrinsify} compiler
+ * option. The C1X 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.sun.c1x.C1XIntrinsic#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, C1X replaces the call to the
+ * method with the result.</li>
+ * </ul>
+ *
+ * <h3>Broken features</h3>
+ *
+ * <ul>
+ * <li>
+ * {@link com.sun.c1x.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 C1X, 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.sun.c1x.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.sun.c1x.target.amd64.AMD64GlobalStubEmitter} controls how the global stubs accept their
+ * parameters. See {@link com.sun.c1x.target.amd64.AMD64GlobalStubEmitter#callerFrameContainsArguments} and its usages.
+ *
+ * </li>
+ * </ul>
+ */
+package com.sun.c1x;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/target/Backend.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.target;
+
+import java.lang.reflect.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.asm.*;
+import com.sun.c1x.gen.*;
+import com.sun.c1x.globalstub.*;
+import com.sun.c1x.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 C1X.
+ *
+ * @author Ben L. Titzer
+ */
+public abstract class Backend {
+    public final C1XCompiler compiler;
+
+    protected Backend(C1XCompiler compiler) {
+        this.compiler = compiler;
+    }
+
+    public static Backend create(CiArchitecture arch, C1XCompiler compiler) {
+        String className = arch.getClass().getName() + "Backend";
+        try {
+            Class<?> c = Class.forName(className);
+            Constructor<?> cons = c.getDeclaredConstructor(C1XCompiler.class);
+            return (Backend) cons.newInstance(compiler);
+        } catch (Exception e) {
+            throw new Error("Could instantiate " + className, e);
+        }
+    }
+
+    public abstract FrameMap newFrameMap(RiMethod method, int numberOfLocks);
+    public abstract LIRGenerator newLIRGenerator(C1XCompilation compilation);
+    public abstract LIRAssembler newLIRAssembler(C1XCompilation 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/Compiler/src/com/sun/c1x/target/amd64/AMD64.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.target.amd64;
+
+import static com.sun.cri.bytecode.Bytecodes.MemoryBarriers.*;
+import static com.sun.cri.ci.CiKind.*;
+import static com.sun.cri.ci.CiRegister.RegisterFlag.*;
+
+import com.sun.cri.ci.*;
+import com.sun.cri.ci.CiRegister.RegisterFlag;
+
+/**
+ * Represents the AMD64 architecture.
+ *
+ * @author Thomas Wuerthinger
+ */
+public class AMD64 extends CiArchitecture {
+
+    // General purpose CPU registers
+    public static final CiRegister rax = new CiRegister(0, 0, 8, "rax", CPU, RegisterFlag.Byte);
+    public static final CiRegister rcx = new CiRegister(1, 1, 8, "rcx", CPU, RegisterFlag.Byte);
+    public static final CiRegister rdx = new CiRegister(2, 2, 8, "rdx", CPU, RegisterFlag.Byte);
+    public static final CiRegister rbx = new CiRegister(3, 3, 8, "rbx", CPU, RegisterFlag.Byte);
+    public static final CiRegister rsp = new CiRegister(4, 4, 8, "rsp", CPU, RegisterFlag.Byte);
+    public static final CiRegister rbp = new CiRegister(5, 5, 8, "rbp", CPU, RegisterFlag.Byte);
+    public static final CiRegister rsi = new CiRegister(6, 6, 8, "rsi", CPU, RegisterFlag.Byte);
+    public static final CiRegister rdi = new CiRegister(7, 7, 8, "rdi", CPU, RegisterFlag.Byte);
+
+    public static final CiRegister r8  = new CiRegister(8,  8,  8, "r8", CPU, RegisterFlag.Byte);
+    public static final CiRegister r9  = new CiRegister(9,  9,  8, "r9", CPU, RegisterFlag.Byte);
+    public static final CiRegister r10 = new CiRegister(10, 10, 8, "r10", CPU, RegisterFlag.Byte);
+    public static final CiRegister r11 = new CiRegister(11, 11, 8, "r11", CPU, RegisterFlag.Byte);
+    public static final CiRegister r12 = new CiRegister(12, 12, 8, "r12", CPU, RegisterFlag.Byte);
+    public static final CiRegister r13 = new CiRegister(13, 13, 8, "r13", CPU, RegisterFlag.Byte);
+    public static final CiRegister r14 = new CiRegister(14, 14, 8, "r14", CPU, RegisterFlag.Byte);
+    public static final CiRegister r15 = new CiRegister(15, 15, 8, "r15", CPU, RegisterFlag.Byte);
+
+    public static final CiRegister[] cpuRegisters = {
+        rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi,
+        r8, r9, r10, r11, r12, r13, r14, r15
+    };
+
+    // XMM registers
+    public static final CiRegister xmm0 = new CiRegister(16, 0, 8, "xmm0", FPU);
+    public static final CiRegister xmm1 = new CiRegister(17, 1, 8, "xmm1", FPU);
+    public static final CiRegister xmm2 = new CiRegister(18, 2, 8, "xmm2", FPU);
+    public static final CiRegister xmm3 = new CiRegister(19, 3, 8, "xmm3", FPU);
+    public static final CiRegister xmm4 = new CiRegister(20, 4, 8, "xmm4", FPU);
+    public static final CiRegister xmm5 = new CiRegister(21, 5, 8, "xmm5", FPU);
+    public static final CiRegister xmm6 = new CiRegister(22, 6, 8, "xmm6", FPU);
+    public static final CiRegister xmm7 = new CiRegister(23, 7, 8, "xmm7", FPU);
+
+    public static final CiRegister xmm8 =  new CiRegister(24,  8, 8, "xmm8",  FPU);
+    public static final CiRegister xmm9 =  new CiRegister(25,  9, 8, "xmm9",  FPU);
+    public static final CiRegister xmm10 = new CiRegister(26, 10, 8, "xmm10", FPU);
+    public static final CiRegister xmm11 = new CiRegister(27, 11, 8, "xmm11", FPU);
+    public static final CiRegister xmm12 = new CiRegister(28, 12, 8, "xmm12", FPU);
+    public static final CiRegister xmm13 = new CiRegister(29, 13, 8, "xmm13", FPU);
+    public static final CiRegister xmm14 = new CiRegister(30, 14, 8, "xmm14", FPU);
+    public static final CiRegister xmm15 = new CiRegister(31, 15, 8, "xmm15", FPU);
+
+    public static final CiRegister[] xmmRegisters = {
+        xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
+        xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
+    };
+
+    public static final CiRegister[] allRegisters = {
+        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
+    };
+
+    public static final CiRegisterValue RSP = rsp.asValue(Word);
+
+    public AMD64() {
+        super("AMD64",
+              8,
+              ByteOrder.LittleEndian,
+              allRegisters,
+              LOAD_STORE | STORE_STORE,
+              1,
+              r15.encoding + 1,
+              8);
+    }
+
+    @Override
+    public boolean isX86() {
+        return true;
+    }
+
+    @Override
+    public boolean twoOperandMode() {
+        return true;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/target/amd64/AMD64Assembler.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,2878 @@
+/*
+ * 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.sun.c1x.target.amd64;
+
+import static com.sun.c1x.target.amd64.AMD64.*;
+import static com.sun.cri.bytecode.Bytecodes.MemoryBarriers.*;
+import static com.sun.cri.ci.CiKind.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.asm.*;
+import com.sun.c1x.lir.*;
+import com.sun.c1x.util.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+/**
+ * This class implements an assembler that can encode most X86 instructions.
+ *
+ * @author Thomas Wuerthinger
+ */
+public class AMD64Assembler extends AbstractAssembler {
+
+    private static final int MinEncodingNeedsRex = 8;
+
+    /**
+     * The x86 condition codes used for conditional jumps/moves.
+     */
+    public enum ConditionFlag {
+        zero(0x4),
+        notZero(0x5),
+        equal(0x4),
+        notEqual(0x5),
+        less(0xc),
+        lessEqual(0xe),
+        greater(0xf),
+        greaterEqual(0xd),
+        below(0x2),
+        belowEqual(0x6),
+        above(0x7),
+        aboveEqual(0x3),
+        overflow(0x0),
+        noOverflow(0x1),
+        carrySet(0x2),
+        carryClear(0x3),
+        negative(0x8),
+        positive(0x9),
+        parity(0xa),
+        noParity(0xb);
+
+        public final int value;
+
+        private ConditionFlag(int value) {
+            this.value = value;
+        }
+
+        public static final ConditionFlag[] values = values();
+    }
+
+    /**
+     * Constants for X86 prefix bytes.
+     */
+    private class Prefix {
+        private static final int REX = 0x40;
+        private static final int REXB = 0x41;
+        private static final int REXX = 0x42;
+        private static final int REXXB = 0x43;
+        private static final int REXR = 0x44;
+        private static final int REXRB = 0x45;
+        private static final int REXRX = 0x46;
+        private static final int REXRXB = 0x47;
+        private static final int REXW = 0x48;
+        private static final int REXWB = 0x49;
+        private static final int REXWX = 0x4A;
+        private static final int REXWXB = 0x4B;
+        private static final int REXWR = 0x4C;
+        private static final int REXWRB = 0x4D;
+        private static final int REXWRX = 0x4E;
+        private static final int REXWRXB = 0x4F;
+    }
+
+    /**
+     * The register to which {@link CiRegister#Frame} and {@link CiRegister#CallerFrame} are bound.
+     */
+    public final CiRegister frameRegister;
+
+    /**
+     * Constructs an assembler for the AMD64 architecture.
+     *
+     * @param registerConfig the register configuration used to bind {@link CiRegister#Frame} and
+     *            {@link CiRegister#CallerFrame} to physical registers. This value can be null if this assembler
+     *            instance will not be used to assemble instructions using these logical registers.
+     */
+    public AMD64Assembler(CiTarget target, RiRegisterConfig registerConfig) {
+        super(target);
+        this.frameRegister = registerConfig == null ? null : registerConfig.getFrameRegister();
+    }
+
+    private static int encode(CiRegister r) {
+        assert r.encoding < 16 && r.encoding >= 0 : "encoding out of range: " + r.encoding;
+        return r.encoding & 0x7;
+    }
+
+    private void emitArithB(int op1, int op2, CiRegister dst, int imm8) {
+        assert dst.isByte() : "must have byte register";
+        assert Util.isUByte(op1) && Util.isUByte(op2) : "wrong opcode";
+        assert Util.isUByte(imm8) : "not a byte";
+        assert (op1 & 0x01) == 0 : "should be 8bit operation";
+        emitByte(op1);
+        emitByte(op2 | encode(dst));
+        emitByte(imm8);
+    }
+
+    private void emitArith(int op1, int op2, CiRegister dst, int imm32) {
+        assert Util.isUByte(op1) && Util.isUByte(op2) : "wrong opcode";
+        assert (op1 & 0x01) == 1 : "should be 32bit operation";
+        assert (op1 & 0x02) == 0 : "sign-extension bit should not be set";
+        if (Util.isByte(imm32)) {
+            emitByte(op1 | 0x02); // set sign bit
+            emitByte(op2 | encode(dst));
+            emitByte(imm32 & 0xFF);
+        } else {
+            emitByte(op1);
+            emitByte(op2 | encode(dst));
+            emitInt(imm32);
+        }
+    }
+
+    // immediate-to-memory forms
+    private void emitArithOperand(int op1, CiRegister rm, CiAddress adr, int imm32) {
+        assert (op1 & 0x01) == 1 : "should be 32bit operation";
+        assert (op1 & 0x02) == 0 : "sign-extension bit should not be set";
+        if (Util.isByte(imm32)) {
+            emitByte(op1 | 0x02); // set sign bit
+            emitOperandHelper(rm, adr);
+            emitByte(imm32 & 0xFF);
+        } else {
+            emitByte(op1);
+            emitOperandHelper(rm, adr);
+            emitInt(imm32);
+        }
+    }
+
+    private void emitArith(int op1, int op2, CiRegister dst, CiRegister src) {
+        assert Util.isUByte(op1) && Util.isUByte(op2) : "wrong opcode";
+        emitByte(op1);
+        emitByte(op2 | encode(dst) << 3 | encode(src));
+    }
+
+    private void emitOperandHelper(CiRegister reg, CiAddress addr) {
+        CiRegister base = addr.base();
+
+        CiRegister index = addr.index();
+        CiAddress.Scale scale = addr.scale;
+        int disp = addr.displacement;
+
+        if (base == CiRegister.Frame) {
+            assert frameRegister != null : "cannot use register " + CiRegister.Frame + " in assembler with null register configuration";
+            base = frameRegister;
+        } else if (base == CiRegister.CallerFrame) {
+            assert frameRegister != null : "cannot use register " + CiRegister.Frame + " in assembler with null register configuration";
+            base = frameRegister;
+            disp += targetMethod.frameSize() + 8;
+        }
+
+        // Encode the registers as needed in the fields they are used in
+
+        assert reg != CiRegister.None;
+
+        int regenc = encode(reg) << 3;
+        int indexenc = index.isValid() ? encode(index) << 3 : 0;
+        int baseenc = base.isValid() ? encode(base) : 0;
+
+        if (base.isValid()) {
+            if (index.isValid()) {
+                // [base + indexscale + disp]
+                if (disp == 0 && base != rbp && (base != r13)) {
+                    // [base + indexscale]
+                    // [00 reg 100][ss index base]
+                    assert index != rsp : "illegal addressing mode";
+                    emitByte(0x04 | regenc);
+                    emitByte(scale.log2 << 6 | indexenc | baseenc);
+                } else if (Util.isByte(disp)) {
+                    // [base + indexscale + imm8]
+                    // [01 reg 100][ss index base] imm8
+                    assert index != rsp : "illegal addressing mode";
+                    emitByte(0x44 | regenc);
+                    emitByte(scale.log2 << 6 | indexenc | baseenc);
+                    emitByte(disp & 0xFF);
+                } else {
+                    // [base + indexscale + disp32]
+                    // [10 reg 100][ss index base] disp32
+                    assert index != rsp : "illegal addressing mode";
+                    emitByte(0x84 | regenc);
+                    emitByte(scale.log2 << 6 | indexenc | baseenc);
+                    emitInt(disp);
+                }
+            } else if (base == rsp || (base == r12)) {
+                // [rsp + disp]
+                if (disp == 0) {
+                    // [rsp]
+                    // [00 reg 100][00 100 100]
+                    emitByte(0x04 | regenc);
+                    emitByte(0x24);
+                } else if (Util.isByte(disp)) {
+                    // [rsp + imm8]
+                    // [01 reg 100][00 100 100] disp8
+                    emitByte(0x44 | regenc);
+                    emitByte(0x24);
+                    emitByte(disp & 0xFF);
+                } else {
+                    // [rsp + imm32]
+                    // [10 reg 100][00 100 100] disp32
+                    emitByte(0x84 | regenc);
+                    emitByte(0x24);
+                    emitInt(disp);
+                }
+            } else {
+                // [base + disp]
+                assert base != rsp && (base != r12) : "illegal addressing mode";
+                if (disp == 0 && base != rbp && (base != r13)) {
+                    // [base]
+                    // [00 reg base]
+                    emitByte(0x00 | regenc | baseenc);
+                } else if (Util.isByte(disp)) {
+                    // [base + disp8]
+                    // [01 reg base] disp8
+                    emitByte(0x40 | regenc | baseenc);
+                    emitByte(disp & 0xFF);
+                } else {
+                    // [base + disp32]
+                    // [10 reg base] disp32
+                    emitByte(0x80 | regenc | baseenc);
+                    emitInt(disp);
+                }
+            }
+        } else {
+            if (index.isValid()) {
+                // [indexscale + disp]
+                // [00 reg 100][ss index 101] disp32
+                assert index != rsp : "illegal addressing mode";
+                emitByte(0x04 | regenc);
+                emitByte(scale.log2 << 6 | indexenc | 0x05);
+                emitInt(disp);
+            } else if (base == CiRegister.InstructionRelative) {
+                // Adjust disp which is currently relative to the start of the instruction
+                int instrStart = codeBuffer.mark();
+                assert instrStart >= 0;
+                int instrSize = (codeBuffer.position() - instrStart) + 5;
+                disp = disp - instrSize;
+                // [00 000 101] disp32
+                emitByte(0x05 | regenc);
+                emitInt(disp);
+            } else if (addr == CiAddress.Placeholder) {
+                // [00 000 101] disp32
+                emitByte(0x05 | regenc);
+                emitInt(0);
+            } else {
+                // [disp] ABSOLUTE
+                // [00 reg 100][00 100 101] disp32
+                emitByte(0x04 | regenc);
+                emitByte(0x25);
+                emitInt(disp);
+            }
+        }
+    }
+
+    public final void addl(CiAddress dst, int imm32) {
+        prefix(dst);
+        emitArithOperand(0x81, rax, dst, imm32);
+    }
+
+    public final void addl(CiAddress dst, CiRegister src) {
+        prefix(dst, src);
+        emitByte(0x01);
+        emitOperandHelper(src, dst);
+    }
+
+    public final void addl(CiRegister dst, int imm32) {
+        prefix(dst);
+        emitArith(0x81, 0xC0, dst, imm32);
+    }
+
+    public final void addl(CiRegister dst, CiAddress src) {
+        prefix(src, dst);
+        emitByte(0x03);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void addl(CiRegister dst, CiRegister src) {
+        prefixAndEncode(dst.encoding, src.encoding);
+        emitArith(0x03, 0xC0, dst, src);
+    }
+
+    private void addrNop4() {
+        // 4 bytes: NOP DWORD PTR [EAX+0]
+        emitByte(0x0F);
+        emitByte(0x1F);
+        emitByte(0x40); // emitRm(cbuf, 0x1, EAXEnc, EAXEnc);
+        emitByte(0); // 8-bits offset (1 byte)
+    }
+
+    private void addrNop5() {
+        // 5 bytes: NOP DWORD PTR [EAX+EAX*0+0] 8-bits offset
+        emitByte(0x0F);
+        emitByte(0x1F);
+        emitByte(0x44); // emitRm(cbuf, 0x1, EAXEnc, 0x4);
+        emitByte(0x00); // emitRm(cbuf, 0x0, EAXEnc, EAXEnc);
+        emitByte(0); // 8-bits offset (1 byte)
+    }
+
+    private void addrNop7() {
+        // 7 bytes: NOP DWORD PTR [EAX+0] 32-bits offset
+        emitByte(0x0F);
+        emitByte(0x1F);
+        emitByte(0x80); // emitRm(cbuf, 0x2, EAXEnc, EAXEnc);
+        emitInt(0); // 32-bits offset (4 bytes)
+    }
+
+    private void addrNop8() {
+        // 8 bytes: NOP DWORD PTR [EAX+EAX*0+0] 32-bits offset
+        emitByte(0x0F);
+        emitByte(0x1F);
+        emitByte(0x84); // emitRm(cbuf, 0x2, EAXEnc, 0x4);
+        emitByte(0x00); // emitRm(cbuf, 0x0, EAXEnc, EAXEnc);
+        emitInt(0); // 32-bits offset (4 bytes)
+    }
+
+    public final void addsd(CiRegister dst, CiRegister src) {
+        assert dst.isFpu() && src.isFpu();
+        emitByte(0xF2);
+        int encode = prefixAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0x58);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void addsd(CiRegister dst, CiAddress src) {
+        assert dst.isFpu();
+        emitByte(0xF2);
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0x58);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void addss(CiRegister dst, CiRegister src) {
+        assert dst.isFpu() && src.isFpu();
+        emitByte(0xF3);
+        int encode = prefixAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0x58);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void addss(CiRegister dst, CiAddress src) {
+        assert dst.isFpu();
+        emitByte(0xF3);
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0x58);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void andl(CiRegister dst, int imm32) {
+        prefix(dst);
+        emitArith(0x81, 0xE0, dst, imm32);
+    }
+
+    public final void andl(CiRegister dst, CiAddress src) {
+        prefix(src, dst);
+        emitByte(0x23);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void andl(CiRegister dst, CiRegister src) {
+        prefixAndEncode(dst.encoding, src.encoding);
+        emitArith(0x23, 0xC0, dst, src);
+    }
+
+    public final void andpd(CiRegister dst, CiAddress src) {
+        assert dst.isFpu();
+        emitByte(0x66);
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0x54);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void bsfq(CiRegister dst, CiRegister src) {
+        int encode = prefixqAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0xBC);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void bsfq(CiRegister dst, CiAddress src) {
+        prefixq(src, dst);
+        emitByte(0xBC);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void bsrq(CiRegister dst, CiRegister src) {
+        int encode = prefixqAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0xBD);
+        emitByte(0xC0 | encode);
+    }
+
+
+    public final void bsrq(CiRegister dst, CiAddress src) {
+        prefixq(src, dst);
+        emitByte(0xBD);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void bswapl(CiRegister reg) { // bswap
+        int encode = prefixAndEncode(reg.encoding);
+        emitByte(0x0F);
+        emitByte(0xC8 | encode);
+    }
+
+    public final void btli(CiAddress src, int imm8) {
+        prefixq(src);
+        emitByte(0x0F);
+        emitByte(0xBA);
+        emitOperandHelper(rsp, src);
+        emitByte(imm8);
+    }
+
+    public final void nativeCall(CiRegister dst, String symbol, LIRDebugInfo info) {
+        int before = codeBuffer.position();
+        int encode = prefixAndEncode(dst.encoding);
+        emitByte(0xFF);
+        emitByte(0xD0 | encode);
+        int after = codeBuffer.position();
+        recordIndirectCall(before, after, symbol, info);
+        recordExceptionHandlers(after, info);
+    }
+
+    public final int directCall(Object target, LIRDebugInfo info) {
+        int before = codeBuffer.position();
+        emitByte(0xE8);
+        emitInt(0);
+        int after = codeBuffer.position();
+        recordDirectCall(before, after, target, info);
+        recordExceptionHandlers(after, info);
+        return before;
+    }
+
+    public final int directJmp(Object target) {
+        int before = codeBuffer.position();
+        emitByte(0xE9);
+        emitInt(0);
+        int after = codeBuffer.position();
+        recordDirectCall(before, after, target, null);
+        return before;
+    }
+
+    public final int indirectCall(CiRegister dst, Object target, LIRDebugInfo info) {
+        int before = codeBuffer.position();
+        int encode = prefixAndEncode(dst.encoding);
+
+        emitByte(0xFF);
+        emitByte(0xD0 | encode);
+        int after = codeBuffer.position();
+        recordIndirectCall(before, after, target, info);
+        recordExceptionHandlers(after, info);
+        return before;
+    }
+
+    public final void cdql() {
+        emitByte(0x99);
+    }
+
+    public final void cmovl(ConditionFlag cc, CiRegister dst, CiRegister src) {
+        int encode = prefixAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0x40 | cc.value);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void cmovl(ConditionFlag cc, CiRegister dst, CiAddress src) {
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0x40 | cc.value);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void cmpb(CiAddress dst, int imm8) {
+        prefix(dst);
+        emitByte(0x80);
+        emitOperandHelper(rdi, dst);
+        emitByte(imm8);
+    }
+
+    public final void cmpl(CiAddress dst, int imm32) {
+        prefix(dst);
+        emitByte(0x81);
+        emitOperandHelper(rdi, dst);
+        emitInt(imm32);
+    }
+
+    public final void cmpl(CiRegister dst, int imm32) {
+        prefix(dst);
+        emitArith(0x81, 0xF8, dst, imm32);
+    }
+
+    public final void cmpl(CiRegister dst, CiRegister src) {
+        prefixAndEncode(dst.encoding, src.encoding);
+        emitArith(0x3B, 0xC0, dst, src);
+    }
+
+    public final void cmpl(CiRegister dst, CiAddress src) {
+        prefix(src, dst);
+        emitByte(0x3B);
+        emitOperandHelper(dst, src);
+    }
+
+    // The 32-bit cmpxchg compares the value at adr with the contents of X86.rax,
+    // and stores reg into adr if so; otherwise, the value at adr is loaded into X86.rax,.
+    // The ZF is set if the compared values were equal, and cleared otherwise.
+    public final void cmpxchgl(CiRegister reg, CiAddress adr) { // cmpxchg
+        if ((C1XOptions.Atomics & 2) != 0) {
+            // caveat: no instructionmark, so this isn't relocatable.
+            // Emit a synthetic, non-atomic, CAS equivalent.
+            // Beware. The synthetic form sets all ICCs, not just ZF.
+            // cmpxchg r,[m] is equivalent to X86.rax, = CAS (m, X86.rax, r)
+            cmpl(rax, adr);
+            movl(rax, adr);
+            if (reg != rax) {
+                Label l = new Label();
+                jcc(ConditionFlag.notEqual, l);
+                movl(adr, reg);
+                bind(l);
+            }
+        } else {
+
+            prefix(adr, reg);
+            emitByte(0x0F);
+            emitByte(0xB1);
+            emitOperandHelper(reg, adr);
+        }
+    }
+
+    public final void comisd(CiRegister dst, CiAddress src) {
+        assert dst.isFpu();
+        // NOTE: dbx seems to decode this as comiss even though the
+        // 0x66 is there. Strangly ucomisd comes out correct
+        emitByte(0x66);
+        comiss(dst, src);
+    }
+
+    public final void comiss(CiRegister dst, CiAddress src) {
+        assert dst.isFpu();
+
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0x2F);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void cvtdq2pd(CiRegister dst, CiRegister src) {
+        assert dst.isFpu();
+        assert src.isFpu();
+
+        emitByte(0xF3);
+        int encode = prefixAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0xE6);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void cvtdq2ps(CiRegister dst, CiRegister src) {
+        assert dst.isFpu();
+        assert src.isFpu();
+        int encode = prefixAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0x5B);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void cvtsd2ss(CiRegister dst, CiRegister src) {
+        assert dst.isFpu();
+        assert src.isFpu();
+        emitByte(0xF2);
+        int encode = prefixAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0x5A);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void cvtsi2sdl(CiRegister dst, CiRegister src) {
+        assert dst.isFpu();
+        emitByte(0xF2);
+        int encode = prefixAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0x2A);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void cvtsi2ssl(CiRegister dst, CiRegister src) {
+        assert dst.isFpu();
+        emitByte(0xF3);
+        int encode = prefixAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0x2A);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void cvtss2sd(CiRegister dst, CiRegister src) {
+        assert dst.isFpu();
+        assert src.isFpu();
+        emitByte(0xF3);
+        int encode = prefixAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0x5A);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void cvttsd2sil(CiRegister dst, CiRegister src) {
+        assert src.isFpu();
+        emitByte(0xF2);
+        int encode = prefixAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0x2C);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void cvttss2sil(CiRegister dst, CiRegister src) {
+        assert src.isFpu();
+        emitByte(0xF3);
+        int encode = prefixAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0x2C);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void decl(CiAddress dst) {
+        // Don't use it directly. Use Macrodecrement() instead.
+        prefix(dst);
+        emitByte(0xFF);
+        emitOperandHelper(rcx, dst);
+    }
+
+    public final void divsd(CiRegister dst, CiAddress src) {
+        assert dst.isFpu();
+        emitByte(0xF2);
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0x5E);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void divsd(CiRegister dst, CiRegister src) {
+        assert dst.isFpu();
+        assert src.isFpu();
+        emitByte(0xF2);
+        int encode = prefixAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0x5E);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void divss(CiRegister dst, CiAddress src) {
+        assert dst.isFpu();
+        emitByte(0xF3);
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0x5E);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void divss(CiRegister dst, CiRegister src) {
+        assert dst.isFpu();
+        assert src.isFpu();
+        emitByte(0xF3);
+        int encode = prefixAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0x5E);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void hlt() {
+        emitByte(0xF4);
+    }
+
+    public final void idivl(CiRegister src) {
+        int encode = prefixAndEncode(src.encoding);
+        emitByte(0xF7);
+        emitByte(0xF8 | encode);
+    }
+
+    public final void imull(CiRegister dst, CiRegister src) {
+        int encode = prefixAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0xAF);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void imull(CiRegister dst, CiRegister src, int value) {
+        int encode = prefixAndEncode(dst.encoding, src.encoding);
+        if (Util.isByte(value)) {
+            emitByte(0x6B);
+            emitByte(0xC0 | encode);
+            emitByte(value);
+        } else {
+            emitByte(0x69);
+            emitByte(0xC0 | encode);
+            emitInt(value);
+        }
+    }
+
+    public final void incl(CiAddress dst) {
+        // Don't use it directly. Use Macroincrement() instead.
+        prefix(dst);
+        emitByte(0xFF);
+        emitOperandHelper(rax, dst);
+    }
+
+    public final void jcc(ConditionFlag cc, int target, boolean forceDisp32) {
+        int shortSize = 2;
+        int longSize = 6;
+        long disp = target - codeBuffer.position();
+        if (!forceDisp32 && Util.isByte(disp - shortSize)) {
+            // 0111 tttn #8-bit disp
+            emitByte(0x70 | cc.value);
+            emitByte((int) ((disp - shortSize) & 0xFF));
+        } else {
+            // 0000 1111 1000 tttn #32-bit disp
+            assert Util.isInt(disp - longSize) : "must be 32bit offset (call4)";
+            emitByte(0x0F);
+            emitByte(0x80 | cc.value);
+            emitInt((int) (disp - longSize));
+        }
+    }
+
+    public final void jcc(ConditionFlag cc, Label l) {
+        assert (0 <= cc.value) && (cc.value < 16) : "illegal cc";
+        if (l.isBound()) {
+            jcc(cc, l.position(), false);
+        } else {
+            // Note: could eliminate cond. jumps to this jump if condition
+            // is the same however, seems to be rather unlikely case.
+            // Note: use jccb() if label to be bound is very close to get
+            // an 8-bit displacement
+            l.addPatchAt(codeBuffer.position());
+            emitByte(0x0F);
+            emitByte(0x80 | cc.value);
+            emitInt(0);
+        }
+
+    }
+
+    public final void jccb(ConditionFlag cc, Label l) {
+        if (l.isBound()) {
+            int shortSize = 2;
+            int entry = l.position();
+            assert Util.isByte(entry - (codeBuffer.position() + shortSize)) : "Dispacement too large for a short jmp";
+            long disp = entry - codeBuffer.position();
+            // 0111 tttn #8-bit disp
+            emitByte(0x70 | cc.value);
+            emitByte((int) ((disp - shortSize) & 0xFF));
+        } else {
+
+            l.addPatchAt(codeBuffer.position());
+            emitByte(0x70 | cc.value);
+            emitByte(0);
+        }
+    }
+
+    public final void jmp(CiAddress adr) {
+        prefix(adr);
+        emitByte(0xFF);
+        emitOperandHelper(rsp, adr);
+    }
+
+    public final void jmp(int target, boolean forceDisp32) {
+        int shortSize = 2;
+        int longSize = 5;
+        long disp = target - codeBuffer.position();
+        if (!forceDisp32 && Util.isByte(disp - shortSize)) {
+            emitByte(0xEB);
+            emitByte((int) ((disp - shortSize) & 0xFF));
+        } else {
+            emitByte(0xE9);
+            emitInt((int) (disp - longSize));
+        }
+    }
+
+    public final void jmp(Label l) {
+        if (l.isBound()) {
+            jmp(l.position(), false);
+        } else {
+            // By default, forward jumps are always 32-bit displacements, since
+            // we can't yet know where the label will be bound. If you're sure that
+            // the forward jump will not run beyond 256 bytes, use jmpb to
+            // force an 8-bit displacement.
+
+            l.addPatchAt(codeBuffer.position());
+            emitByte(0xE9);
+            emitInt(0);
+        }
+    }
+
+    public final void jmp(CiRegister entry) {
+        int encode = prefixAndEncode(entry.encoding);
+        emitByte(0xFF);
+        emitByte(0xE0 | encode);
+    }
+
+    public final void jmpb(Label l) {
+        if (l.isBound()) {
+            int shortSize = 2;
+            int entry = l.position();
+            assert Util.isByte((entry - codeBuffer.position()) + shortSize) : "Dispacement too large for a short jmp";
+            long offs = entry - codeBuffer.position();
+            emitByte(0xEB);
+            emitByte((int) ((offs - shortSize) & 0xFF));
+        } else {
+
+            l.addPatchAt(codeBuffer.position());
+            emitByte(0xEB);
+            emitByte(0);
+        }
+    }
+
+    public final void leaq(CiRegister dst, CiAddress src) {
+        prefixq(src, dst);
+        emitByte(0x8D);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void enter(int imm16, int imm8) {
+        emitByte(0xC8);
+        emitShort(imm16);
+        emitByte(imm8);
+    }
+
+    public final void leave() {
+        emitByte(0xC9);
+    }
+
+    public final void lock() {
+        if ((C1XOptions.Atomics & 1) != 0) {
+            // Emit either nothing, a NOP, or a NOP: prefix
+            emitByte(0x90);
+        } else {
+            emitByte(0xF0);
+        }
+    }
+
+    // Emit mfence instruction
+    public final void mfence() {
+        emitByte(0x0F);
+        emitByte(0xAE);
+        emitByte(0xF0);
+    }
+
+    public final void mov(CiRegister dst, CiRegister src) {
+        movq(dst, src);
+    }
+
+    public final void movapd(CiRegister dst, CiRegister src) {
+        assert dst.isFpu();
+        assert src.isFpu();
+        int dstenc = dst.encoding;
+        int srcenc = src.encoding;
+        emitByte(0x66);
+        if (dstenc < 8) {
+            if (srcenc >= 8) {
+                emitByte(Prefix.REXB);
+                srcenc -= 8;
+            }
+        } else {
+            if (srcenc < 8) {
+                emitByte(Prefix.REXR);
+            } else {
+                emitByte(Prefix.REXRB);
+                srcenc -= 8;
+            }
+            dstenc -= 8;
+        }
+        emitByte(0x0F);
+        emitByte(0x28);
+        emitByte(0xC0 | dstenc << 3 | srcenc);
+    }
+
+    public final void movaps(CiRegister dst, CiRegister src) {
+        assert dst.isFpu();
+        assert src.isFpu();
+        int dstenc = dst.encoding;
+        int srcenc = src.encoding;
+        if (dstenc < 8) {
+            if (srcenc >= 8) {
+                emitByte(Prefix.REXB);
+                srcenc -= 8;
+            }
+        } else {
+            if (srcenc < 8) {
+                emitByte(Prefix.REXR);
+            } else {
+                emitByte(Prefix.REXRB);
+                srcenc -= 8;
+            }
+            dstenc -= 8;
+        }
+        emitByte(0x0F);
+        emitByte(0x28);
+        emitByte(0xC0 | dstenc << 3 | srcenc);
+    }
+
+    public final void movb(CiRegister dst, CiAddress src) {
+        prefix(src, dst); // , true)
+        emitByte(0x8A);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void movb(CiAddress dst, int imm8) {
+        prefix(dst);
+        emitByte(0xC6);
+        emitOperandHelper(rax, dst);
+        emitByte(imm8);
+    }
+
+    public final void movb(CiAddress dst, CiRegister src) {
+        assert src.isByte() : "must have byte register";
+        prefix(dst, src); // , true)
+        emitByte(0x88);
+        emitOperandHelper(src, dst);
+    }
+
+    public final void movdl(CiRegister dst, CiRegister src) {
+        if (dst.isFpu()) {
+            assert !src.isFpu() : "does this hold?";
+            emitByte(0x66);
+            int encode = prefixAndEncode(dst.encoding, src.encoding);
+            emitByte(0x0F);
+            emitByte(0x6E);
+            emitByte(0xC0 | encode);
+        } else if (src.isFpu()) {
+            assert !dst.isFpu();
+            emitByte(0x66);
+            // swap src/dst to get correct prefix
+            int encode = prefixAndEncode(src.encoding, dst.encoding);
+            emitByte(0x0F);
+            emitByte(0x7E);
+            emitByte(0xC0 | encode);
+        }
+    }
+
+    public final void movdqa(CiRegister dst, CiAddress src) {
+        assert dst.isFpu();
+        emitByte(0x66);
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0x6F);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void movdqa(CiRegister dst, CiRegister src) {
+        assert dst.isFpu();
+        emitByte(0x66);
+        int encode = prefixqAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0x6F);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void movdqa(CiAddress dst, CiRegister src) {
+        assert src.isFpu();
+        emitByte(0x66);
+        prefix(dst, src);
+        emitByte(0x0F);
+        emitByte(0x7F);
+        emitOperandHelper(src, dst);
+    }
+
+    public final void movdqu(CiRegister dst, CiAddress src) {
+        assert dst.isFpu();
+        emitByte(0xF3);
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0x6F);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void movdqu(CiRegister dst, CiRegister src) {
+        assert dst.isFpu();
+        assert src.isFpu();
+
+        emitByte(0xF3);
+        int encode = prefixqAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0x6F);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void movdqu(CiAddress dst, CiRegister src) {
+        assert src.isFpu();
+
+        emitByte(0xF3);
+        prefix(dst, src);
+        emitByte(0x0F);
+        emitByte(0x7F);
+        emitOperandHelper(src, dst);
+    }
+
+    public final void movl(CiRegister dst, int imm32) {
+        int encode = prefixAndEncode(dst.encoding);
+        emitByte(0xB8 | encode);
+        emitInt(imm32);
+    }
+
+    public final void movl(CiRegister dst, CiRegister src) {
+        int encode = prefixAndEncode(dst.encoding, src.encoding);
+        emitByte(0x8B);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void movl(CiRegister dst, CiAddress src) {
+        prefix(src, dst);
+        emitByte(0x8B);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void movl(CiAddress dst, int imm32) {
+        prefix(dst);
+        emitByte(0xC7);
+        emitOperandHelper(rax, dst);
+        emitInt(imm32);
+    }
+
+    public final void movl(CiAddress dst, CiRegister src) {
+        prefix(dst, src);
+        emitByte(0x89);
+        emitOperandHelper(src, dst);
+    }
+
+    // New cpus require to use movsd and movss to avoid partial register stall
+    // when loading from memory. But for old Opteron use movlpd instead of movsd.
+    // The selection is done in Macromovdbl() and movflt().
+    public final void movlpd(CiRegister dst, CiAddress src) {
+        assert dst.isFpu();
+
+        emitByte(0x66);
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0x12);
+        emitOperandHelper(dst, src);
+
+    }
+
+    public final void movq(CiRegister dst, CiAddress src) {
+        if (dst.isFpu()) {
+            emitByte(0xF3);
+            prefixq(src, dst);
+            emitByte(0x0F);
+            emitByte(0x7E);
+            emitOperandHelper(dst, src);
+        } else {
+            prefixq(src, dst);
+            emitByte(0x8B);
+            emitOperandHelper(dst, src);
+        }
+    }
+
+    public final void movq(CiRegister dst, CiRegister src) {
+        int encode = prefixqAndEncode(dst.encoding, src.encoding);
+        emitByte(0x8B);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void movq(CiAddress dst, CiRegister src) {
+        if (src.isFpu()) {
+            emitByte(0x66);
+            prefixq(dst, src);
+            emitByte(0x0F);
+            emitByte(0xD6);
+            emitOperandHelper(src, dst);
+        } else {
+            prefixq(dst, src);
+            emitByte(0x89);
+            emitOperandHelper(src, dst);
+        }
+    }
+
+    public final void movsxb(CiRegister dst, CiAddress src) { // movsxb
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0xBE);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void movsxb(CiRegister dst, CiRegister src) { // movsxb
+        int encode = prefixAndEncode(dst.encoding, src.encoding, true);
+        emitByte(0x0F);
+        emitByte(0xBE);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void movsd(CiRegister dst, CiRegister src) {
+        assert dst.isFpu();
+        assert src.isFpu();
+        emitByte(0xF2);
+        int encode = prefixAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0x10);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void movsd(CiRegister dst, CiAddress src) {
+        assert dst.isFpu();
+        emitByte(0xF2);
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0x10);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void movsd(CiAddress dst, CiRegister src) {
+        assert src.isFpu();
+        emitByte(0xF2);
+        prefix(dst, src);
+        emitByte(0x0F);
+        emitByte(0x11);
+        emitOperandHelper(src, dst);
+    }
+
+    public final void movss(CiRegister dst, CiRegister src) {
+        assert dst.isFpu();
+        assert src.isFpu();
+        emitByte(0xF3);
+        int encode = prefixAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0x10);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void movss(CiRegister dst, CiAddress src) {
+        assert dst.isFpu();
+        emitByte(0xF3);
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0x10);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void movss(CiAddress dst, CiRegister src) {
+        assert src.isFpu();
+        emitByte(0xF3);
+        prefix(dst, src);
+        emitByte(0x0F);
+        emitByte(0x11);
+        emitOperandHelper(src, dst);
+    }
+
+    public final void movswl(CiRegister dst, CiAddress src) {
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0xBF);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void movsxw(CiRegister dst, CiRegister src) { // movsxw
+        int encode = prefixAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0xBF);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void movsxw(CiRegister dst, CiAddress src) { // movsxw
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0xBF);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void movzxd(CiRegister dst, CiRegister src) { // movzxd
+        int encode = prefixAndEncode(dst.encoding, src.encoding);
+        emitByte(0x63);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void movzxd(CiRegister dst, CiAddress src) { // movzxd
+        prefix(src, dst);
+        emitByte(0x63);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void movw(CiAddress dst, int imm16) {
+        emitByte(0x66); // switch to 16-bit mode
+        prefix(dst);
+        emitByte(0xC7);
+        emitOperandHelper(rax, dst);
+        emitShort(imm16);
+    }
+
+    public final void movw(CiRegister dst, CiAddress src) {
+        emitByte(0x66);
+        prefix(src, dst);
+        emitByte(0x8B);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void movw(CiAddress dst, CiRegister src) {
+        emitByte(0x66);
+        prefix(dst, src);
+        emitByte(0x89);
+        emitOperandHelper(src, dst);
+    }
+
+    public final void movzxb(CiRegister dst, CiAddress src) { // movzxb
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0xB6);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void movzxb(CiRegister dst, CiRegister src) { // movzxb
+        int encode = prefixAndEncode(dst.encoding, src.encoding, true);
+        emitByte(0x0F);
+        emitByte(0xB6);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void movzxl(CiRegister dst, CiAddress src) { // movzxw
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0xB7);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void movzxl(CiRegister dst, CiRegister src) { // movzxw
+        int encode = prefixAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0xB7);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void mull(CiAddress src) {
+        prefix(src);
+        emitByte(0xF7);
+        emitOperandHelper(rsp, src);
+    }
+
+    public final void mulsd(CiRegister dst, CiAddress src) {
+        assert dst.isFpu();
+        emitByte(0xF2);
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0x59);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void mulsd(CiRegister dst, CiRegister src) {
+        assert dst.isFpu();
+        assert src.isFpu();
+
+        emitByte(0xF2);
+        int encode = prefixAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0x59);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void mulss(CiRegister dst, CiAddress src) {
+        assert dst.isFpu();
+
+        emitByte(0xF3);
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0x59);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void mulss(CiRegister dst, CiRegister src) {
+        assert dst.isFpu();
+        assert src.isFpu();
+        emitByte(0xF3);
+        int encode = prefixAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0x59);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void negl(CiRegister dst) {
+        int encode = prefixAndEncode(dst.encoding);
+        emitByte(0xF7);
+        emitByte(0xD8 | encode);
+    }
+
+    @Override
+    public final void nop() {
+        nop(1);
+    }
+
+    public void nop(int i) {
+        if (C1XOptions.UseNormalNop) {
+            assert i > 0 : " ";
+            // The fancy nops aren't currently recognized by debuggers making it a
+            // pain to disassemble code while debugging. If assert are on clearly
+            // speed is not an issue so simply use the single byte traditional nop
+            // to do alignment.
+
+            for (; i > 0; i--) {
+                emitByte(0x90);
+            }
+            return;
+        }
+
+        if (C1XOptions.UseAddressNop) {
+            //
+            // Using multi-bytes nops "0x0F 0x1F [Address]" for AMD.
+            // 1: 0x90
+            // 2: 0x66 0x90
+            // 3: 0x66 0x66 0x90 (don't use "0x0F 0x1F 0x00" - need patching safe padding)
+            // 4: 0x0F 0x1F 0x40 0x00
+            // 5: 0x0F 0x1F 0x44 0x00 0x00
+            // 6: 0x66 0x0F 0x1F 0x44 0x00 0x00
+            // 7: 0x0F 0x1F 0x80 0x00 0x00 0x00 0x00
+            // 8: 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00
+            // 9: 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00
+            // 10: 0x66 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00
+            // 11: 0x66 0x66 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00
+
+            // The rest coding is AMD specific - use consecutive Address nops
+
+            // 12: 0x66 0x0F 0x1F 0x44 0x00 0x00 0x66 0x0F 0x1F 0x44 0x00 0x00
+            // 13: 0x0F 0x1F 0x80 0x00 0x00 0x00 0x00 0x66 0x0F 0x1F 0x44 0x00 0x00
+            // 14: 0x0F 0x1F 0x80 0x00 0x00 0x00 0x00 0x0F 0x1F 0x80 0x00 0x00 0x00 0x00
+            // 15: 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00 0x0F 0x1F 0x80 0x00 0x00 0x00 0x00
+            // 16: 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00
+            // Size prefixes (0x66) are added for larger sizes
+
+            while (i >= 22) {
+                i -= 11;
+                emitByte(0x66); // size prefix
+                emitByte(0x66); // size prefix
+                emitByte(0x66); // size prefix
+                addrNop8();
+            }
+            // Generate first nop for size between 21-12
+            switch (i) {
+                case 21:
+                    i -= 1;
+                    emitByte(0x66); // size prefix
+                    // fall through
+                case 20:
+                    // fall through
+                case 19:
+                    i -= 1;
+                    emitByte(0x66); // size prefix
+                    // fall through
+                case 18:
+                    // fall through
+                case 17:
+                    i -= 1;
+                    emitByte(0x66); // size prefix
+                    // fall through
+                case 16:
+                    // fall through
+                case 15:
+                    i -= 8;
+                    addrNop8();
+                    break;
+                case 14:
+                case 13:
+                    i -= 7;
+                    addrNop7();
+                    break;
+                case 12:
+                    i -= 6;
+                    emitByte(0x66); // size prefix
+                    addrNop5();
+                    break;
+                default:
+                    assert i < 12;
+            }
+
+            // Generate second nop for size between 11-1
+            switch (i) {
+                case 11:
+                    emitByte(0x66); // size prefix
+                    emitByte(0x66); // size prefix
+                    emitByte(0x66); // size prefix
+                    addrNop8();
+                    break;
+                case 10:
+                    emitByte(0x66); // size prefix
+                    emitByte(0x66); // size prefix
+                    addrNop8();
+                    break;
+                case 9:
+                    emitByte(0x66); // size prefix
+                    addrNop8();
+                    break;
+                case 8:
+                    addrNop8();
+                    break;
+                case 7:
+                    addrNop7();
+                    break;
+                case 6:
+                    emitByte(0x66); // size prefix
+                    addrNop5();
+                    break;
+                case 5:
+                    addrNop5();
+                    break;
+                case 4:
+                    addrNop4();
+                    break;
+                case 3:
+                    // Don't use "0x0F 0x1F 0x00" - need patching safe padding
+                    emitByte(0x66); // size prefix
+                    emitByte(0x66); // size prefix
+                    emitByte(0x90); // nop
+                    break;
+                case 2:
+                    emitByte(0x66); // size prefix
+                    emitByte(0x90); // nop
+                    break;
+                case 1:
+                    emitByte(0x90); // nop
+                    break;
+                default:
+                    assert i == 0;
+            }
+            return;
+        }
+
+        // Using nops with size prefixes "0x66 0x90".
+        // From AMD Optimization Guide:
+        // 1: 0x90
+        // 2: 0x66 0x90
+        // 3: 0x66 0x66 0x90
+        // 4: 0x66 0x66 0x66 0x90
+        // 5: 0x66 0x66 0x90 0x66 0x90
+        // 6: 0x66 0x66 0x90 0x66 0x66 0x90
+        // 7: 0x66 0x66 0x66 0x90 0x66 0x66 0x90
+        // 8: 0x66 0x66 0x66 0x90 0x66 0x66 0x66 0x90
+        // 9: 0x66 0x66 0x90 0x66 0x66 0x90 0x66 0x66 0x90
+        // 10: 0x66 0x66 0x66 0x90 0x66 0x66 0x90 0x66 0x66 0x90
+        //
+        while (i > 12) {
+            i -= 4;
+            emitByte(0x66); // size prefix
+            emitByte(0x66);
+            emitByte(0x66);
+            emitByte(0x90); // nop
+        }
+        // 1 - 12 nops
+        if (i > 8) {
+            if (i > 9) {
+                i -= 1;
+                emitByte(0x66);
+            }
+            i -= 3;
+            emitByte(0x66);
+            emitByte(0x66);
+            emitByte(0x90);
+        }
+        // 1 - 8 nops
+        if (i > 4) {
+            if (i > 6) {
+                i -= 1;
+                emitByte(0x66);
+            }
+            i -= 3;
+            emitByte(0x66);
+            emitByte(0x66);
+            emitByte(0x90);
+        }
+        switch (i) {
+            case 4:
+                emitByte(0x66);
+                emitByte(0x66);
+                emitByte(0x66);
+                emitByte(0x90);
+                break;
+            case 3:
+                emitByte(0x66);
+                emitByte(0x66);
+                emitByte(0x90);
+                break;
+            case 2:
+                emitByte(0x66);
+                emitByte(0x90);
+                break;
+            case 1:
+                emitByte(0x90);
+                break;
+            default:
+                assert i == 0;
+        }
+    }
+
+    public final void notl(CiRegister dst) {
+        int encode = prefixAndEncode(dst.encoding);
+        emitByte(0xF7);
+        emitByte(0xD0 | encode);
+    }
+
+    public final void orl(CiAddress dst, int imm32) {
+        prefix(dst);
+        emitByte(0x81);
+        emitOperandHelper(rcx, dst);
+        emitInt(imm32);
+    }
+
+    public final void orl(CiRegister dst, int imm32) {
+        prefix(dst);
+        emitArith(0x81, 0xC8, dst, imm32);
+    }
+
+    public final void orl(CiRegister dst, CiAddress src) {
+        prefix(src, dst);
+        emitByte(0x0B);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void orl(CiRegister dst, CiRegister src) {
+        prefixAndEncode(dst.encoding, src.encoding);
+        emitArith(0x0B, 0xC0, dst, src);
+    }
+
+    // generic
+    public final void pop(CiRegister dst) {
+        int encode = prefixAndEncode(dst.encoding);
+        emitByte(0x58 | encode);
+    }
+
+    public final void popl(CiAddress dst) {
+        // NOTE: this will adjust stack by 8byte on 64bits
+        prefix(dst);
+        emitByte(0x8F);
+        emitOperandHelper(rax, dst);
+    }
+
+    public final void prefetchPrefix(CiAddress src) {
+        prefix(src);
+        emitByte(0x0F);
+    }
+
+    public final void prefetchnta(CiAddress src) {
+        prefetchPrefix(src);
+        emitByte(0x18);
+        emitOperandHelper(rax, src); // 0, src
+    }
+
+    public final void prefetchr(CiAddress src) {
+        prefetchPrefix(src);
+        emitByte(0x0D);
+        emitOperandHelper(rax, src); // 0, src
+    }
+
+    public final void prefetcht0(CiAddress src) {
+        prefetchPrefix(src);
+        emitByte(0x18);
+        emitOperandHelper(rcx, src); // 1, src
+
+    }
+
+    public final void prefetcht1(CiAddress src) {
+        prefetchPrefix(src);
+        emitByte(0x18);
+        emitOperandHelper(rdx, src); // 2, src
+    }
+
+    public final void prefetcht2(CiAddress src) {
+        prefetchPrefix(src);
+        emitByte(0x18);
+        emitOperandHelper(rbx, src); // 3, src
+    }
+
+    public final void prefetchw(CiAddress src) {
+        prefetchPrefix(src);
+        emitByte(0x0D);
+        emitOperandHelper(rcx, src); // 1, src
+    }
+
+    public final void pshufd(CiRegister dst, CiRegister src, int mode) {
+        assert dst.isFpu();
+        assert src.isFpu();
+        assert Util.isUByte(mode) : "invalid value";
+
+        emitByte(0x66);
+        int encode = prefixAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0x70);
+        emitByte(0xC0 | encode);
+        emitByte(mode & 0xFF);
+    }
+
+    public final void pshufd(CiRegister dst, CiAddress src, int mode) {
+        assert dst.isFpu();
+        assert Util.isUByte(mode) : "invalid value";
+
+        emitByte(0x66);
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0x70);
+        emitOperandHelper(dst, src);
+        emitByte(mode & 0xFF);
+
+    }
+
+    public final void pshuflw(CiRegister dst, CiRegister src, int mode) {
+        assert dst.isFpu();
+        assert src.isFpu();
+        assert Util.isUByte(mode) : "invalid value";
+
+        emitByte(0xF2);
+        int encode = prefixAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0x70);
+        emitByte(0xC0 | encode);
+        emitByte(mode & 0xFF);
+    }
+
+    public final void pshuflw(CiRegister dst, CiAddress src, int mode) {
+        assert dst.isFpu();
+        assert Util.isUByte(mode) : "invalid value";
+
+        emitByte(0xF2);
+        prefix(src, dst); // QQ new
+        emitByte(0x0F);
+        emitByte(0x70);
+        emitOperandHelper(dst, src);
+        emitByte(mode & 0xFF);
+    }
+
+    public final void psrlq(CiRegister dst, int shift) {
+        assert dst.isFpu();
+        // HMM Table D-1 says sse2 or mmx
+
+        int encode = prefixqAndEncode(xmm2.encoding, dst.encoding);
+        emitByte(0x66);
+        emitByte(0x0F);
+        emitByte(0x73);
+        emitByte(0xC0 | encode);
+        emitByte(shift);
+    }
+
+    public final void punpcklbw(CiRegister dst, CiRegister src) {
+        assert dst.isFpu();
+        assert src.isFpu();
+        emitByte(0x66);
+        int encode = prefixAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0x60);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void push(int imm32) {
+        // in 64bits we push 64bits onto the stack but only
+        // take a 32bit immediate
+        emitByte(0x68);
+        emitInt(imm32);
+    }
+
+    public final void push(CiRegister src) {
+        int encode = prefixAndEncode(src.encoding);
+        emitByte(0x50 | encode);
+    }
+
+    public final void pushf() {
+        emitByte(0x9C);
+    }
+
+    public final void pushl(CiAddress src) {
+        // Note this will push 64bit on 64bit
+        prefix(src);
+        emitByte(0xFF);
+        emitOperandHelper(rsi, src);
+    }
+
+    public final void pxor(CiRegister dst, CiAddress src) {
+        assert dst.isFpu();
+
+        emitByte(0x66);
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0xEF);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void pxor(CiRegister dst, CiRegister src) {
+        assert dst.isFpu();
+        assert src.isFpu();
+
+        emitByte(0x66);
+        int encode = prefixAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0xEF);
+        emitByte(0xC0 | encode);
+
+    }
+
+    public final void rcll(CiRegister dst, int imm8) {
+        assert Util.isShiftCount(imm8) : "illegal shift count";
+        int encode = prefixAndEncode(dst.encoding);
+        if (imm8 == 1) {
+            emitByte(0xD1);
+            emitByte(0xD0 | encode);
+        } else {
+            emitByte(0xC1);
+            emitByte(0xD0 | encode);
+            emitByte(imm8);
+        }
+    }
+
+    public final void pause() {
+        emitByte(0xF3);
+        emitByte(0x90);
+    }
+
+    // Copies data from [X86.rsi] to [X86.rdi] using X86.rcx heap words.
+    public final void repeatMoveWords() {
+        emitByte(0xF3);
+        emitByte(Prefix.REXW);
+        emitByte(0xA5);
+    }
+
+    // Copies data from [X86.rsi] to [X86.rdi] using X86.rcx bytes.
+    public final void repeatMoveBytes() {
+        emitByte(0xF3);
+        emitByte(Prefix.REXW);
+        emitByte(0xA4);
+    }
+
+    // sets X86.rcx pointer sized words with X86.rax, value at [edi]
+    // generic
+    public final void repSet() { // repSet
+        emitByte(0xF3);
+        // STOSQ
+        emitByte(Prefix.REXW);
+        emitByte(0xAB);
+    }
+
+    // scans X86.rcx pointer sized words at [edi] for occurance of X86.rax,
+    // generic
+    public final void repneScan() { // repneScan
+        emitByte(0xF2);
+        // SCASQ
+        emitByte(Prefix.REXW);
+        emitByte(0xAF);
+    }
+
+    // scans X86.rcx 4 byte words at [edi] for occurance of X86.rax,
+    // generic
+    public final void repneScanl() { // repneScan
+        emitByte(0xF2);
+        // SCASL
+        emitByte(0xAF);
+    }
+
+    public final void ret(int imm16) {
+        if (imm16 == 0) {
+            emitByte(0xC3);
+        } else {
+            emitByte(0xC2);
+            emitShort(imm16);
+        }
+    }
+
+    public final void sarl(CiRegister dst, int imm8) {
+        int encode = prefixAndEncode(dst.encoding);
+        assert Util.isShiftCount(imm8) : "illegal shift count";
+        if (imm8 == 1) {
+            emitByte(0xD1);
+            emitByte(0xF8 | encode);
+        } else {
+            emitByte(0xC1);
+            emitByte(0xF8 | encode);
+            emitByte(imm8);
+        }
+    }
+
+    public final void sarl(CiRegister dst) {
+        int encode = prefixAndEncode(dst.encoding);
+        emitByte(0xD3);
+        emitByte(0xF8 | encode);
+    }
+
+    public final void sbbl(CiAddress dst, int imm32) {
+        prefix(dst);
+        emitArithOperand(0x81, rbx, dst, imm32);
+    }
+
+    public final void sbbl(CiRegister dst, int imm32) {
+        prefix(dst);
+        emitArith(0x81, 0xD8, dst, imm32);
+    }
+
+    public final void sbbl(CiRegister dst, CiAddress src) {
+        prefix(src, dst);
+        emitByte(0x1B);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void sbbl(CiRegister dst, CiRegister src) {
+        prefixAndEncode(dst.encoding, src.encoding);
+        emitArith(0x1B, 0xC0, dst, src);
+    }
+
+    public final void setb(ConditionFlag cc, CiRegister dst) {
+        assert 0 <= cc.value && cc.value < 16 : "illegal cc";
+        int encode = prefixAndEncode(dst.encoding, true);
+        emitByte(0x0F);
+        emitByte(0x90 | cc.value);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void shll(CiRegister dst, int imm8) {
+        assert Util.isShiftCount(imm8) : "illegal shift count";
+        int encode = prefixAndEncode(dst.encoding);
+        if (imm8 == 1) {
+            emitByte(0xD1);
+            emitByte(0xE0 | encode);
+        } else {
+            emitByte(0xC1);
+            emitByte(0xE0 | encode);
+            emitByte(imm8);
+        }
+    }
+
+    public final void shll(CiRegister dst) {
+        int encode = prefixAndEncode(dst.encoding);
+        emitByte(0xD3);
+        emitByte(0xE0 | encode);
+    }
+
+    public final void shrl(CiRegister dst, int imm8) {
+        assert Util.isShiftCount(imm8) : "illegal shift count";
+        int encode = prefixAndEncode(dst.encoding);
+        emitByte(0xC1);
+        emitByte(0xE8 | encode);
+        emitByte(imm8);
+    }
+
+    public final void shrl(CiRegister dst) {
+        int encode = prefixAndEncode(dst.encoding);
+        emitByte(0xD3);
+        emitByte(0xE8 | encode);
+    }
+
+    // copies a single word from [esi] to [edi]
+    public final void smovl() {
+        emitByte(0xA5);
+    }
+
+    public final void sqrtsd(CiRegister dst, CiRegister src) {
+        assert dst.isFpu();
+        assert src.isFpu();
+        // HMM Table D-1 says sse2
+        // assert is64 || target.supportsSSE();
+        emitByte(0xF2);
+        int encode = prefixAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0x51);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void subl(CiAddress dst, int imm32) {
+        prefix(dst);
+        if (Util.isByte(imm32)) {
+            emitByte(0x83);
+            emitOperandHelper(rbp, dst);
+            emitByte(imm32 & 0xFF);
+        } else {
+            emitByte(0x81);
+            emitOperandHelper(rbp, dst);
+            emitInt(imm32);
+        }
+    }
+
+    public final void subl(CiRegister dst, int imm32) {
+        prefix(dst);
+        emitArith(0x81, 0xE8, dst, imm32);
+    }
+
+    public final void subl(CiAddress dst, CiRegister src) {
+        prefix(dst, src);
+        emitByte(0x29);
+        emitOperandHelper(src, dst);
+    }
+
+    public final void subl(CiRegister dst, CiAddress src) {
+        prefix(src, dst);
+        emitByte(0x2B);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void subl(CiRegister dst, CiRegister src) {
+        prefixAndEncode(dst.encoding, src.encoding);
+        emitArith(0x2B, 0xC0, dst, src);
+    }
+
+    public final void subsd(CiRegister dst, CiRegister src) {
+        assert dst.isFpu();
+        assert src.isFpu();
+        emitByte(0xF2);
+        int encode = prefixAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0x5C);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void subsd(CiRegister dst, CiAddress src) {
+        assert dst.isFpu();
+
+        emitByte(0xF2);
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0x5C);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void subss(CiRegister dst, CiRegister src) {
+        assert dst.isFpu();
+        assert src.isFpu();
+        emitByte(0xF3);
+        int encode = prefixAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0x5C);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void subss(CiRegister dst, CiAddress src) {
+        assert dst.isFpu();
+
+        emitByte(0xF3);
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0x5C);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void testb(CiRegister dst, int imm8) {
+        prefixAndEncode(dst.encoding, true);
+        emitArithB(0xF6, 0xC0, dst, imm8);
+    }
+
+    public final void testl(CiRegister dst, int imm32) {
+        // not using emitArith because test
+        // doesn't support sign-extension of
+        // 8bit operands
+        int encode = dst.encoding;
+        if (encode == 0) {
+            emitByte(0xA9);
+        } else {
+            encode = prefixAndEncode(encode);
+            emitByte(0xF7);
+            emitByte(0xC0 | encode);
+        }
+        emitInt(imm32);
+    }
+
+    public final void testl(CiRegister dst, CiRegister src) {
+        prefixAndEncode(dst.encoding, src.encoding);
+        emitArith(0x85, 0xC0, dst, src);
+    }
+
+    public final void testl(CiRegister dst, CiAddress src) {
+        prefix(src, dst);
+        emitByte(0x85);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void ucomisd(CiRegister dst, CiAddress src) {
+        assert dst.isFpu();
+        emitByte(0x66);
+        ucomiss(dst, src);
+    }
+
+    public final void ucomisd(CiRegister dst, CiRegister src) {
+        assert dst.isFpu();
+        assert src.isFpu();
+        emitByte(0x66);
+        ucomiss(dst, src);
+    }
+
+    public final void ucomiss(CiRegister dst, CiAddress src) {
+        assert dst.isFpu();
+
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0x2E);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void ucomiss(CiRegister dst, CiRegister src) {
+        assert dst.isFpu();
+        assert src.isFpu();
+        int encode = prefixAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0x2E);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void xaddl(CiAddress dst, CiRegister src) {
+        assert src.isFpu();
+
+        prefix(dst, src);
+        emitByte(0x0F);
+        emitByte(0xC1);
+        emitOperandHelper(src, dst);
+    }
+
+    public final void xchgl(CiRegister dst, CiAddress src) { // xchg
+        prefix(src, dst);
+        emitByte(0x87);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void xchgl(CiRegister dst, CiRegister src) {
+        int encode = prefixAndEncode(dst.encoding, src.encoding);
+        emitByte(0x87);
+        emitByte(0xc0 | encode);
+    }
+
+    public final void xorl(CiRegister dst, int imm32) {
+        prefix(dst);
+        emitArith(0x81, 0xF0, dst, imm32);
+    }
+
+    public final void xorl(CiRegister dst, CiAddress src) {
+        prefix(src, dst);
+        emitByte(0x33);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void xorl(CiRegister dst, CiRegister src) {
+        prefixAndEncode(dst.encoding, src.encoding);
+        emitArith(0x33, 0xC0, dst, src);
+    }
+
+    public final void xorpd(CiRegister dst, CiRegister src) {
+        assert dst.isFpu();
+        assert src.isFpu();
+        emitByte(0x66);
+        xorps(dst, src);
+    }
+
+    public final void xorpd(CiRegister dst, CiAddress src) {
+        assert dst.isFpu();
+
+        emitByte(0x66);
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0x57);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void xorps(CiRegister dst, CiRegister src) {
+
+        assert dst.isFpu();
+        int encode = prefixAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0x57);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void xorps(CiRegister dst, CiAddress src) {
+        assert dst.isFpu();
+
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0x57);
+        emitOperandHelper(dst, src);
+    }
+
+    // 32bit only pieces of the assembler
+
+    public final void decl(CiRegister dst) {
+        // Don't use it directly. Use Macrodecrementl() instead.
+        // Use two-byte form (one-byte form is a REX prefix in 64-bit mode)
+        int encode = prefixAndEncode(dst.encoding);
+        emitByte(0xFF);
+        emitByte(0xC8 | encode);
+    }
+
+    public final void incl(CiRegister dst) {
+        // Don't use it directly. Use Macroincrementl() instead.
+        // Use two-byte form (one-byte from is a REX prefix in 64-bit mode)
+        int encode = prefixAndEncode(dst.encoding);
+        emitByte(0xFF);
+        emitByte(0xC0 | encode);
+    }
+
+    int prefixAndEncode(int regEnc) {
+        return prefixAndEncode(regEnc, false);
+    }
+
+    int prefixAndEncode(int regEnc, boolean byteinst) {
+        if (regEnc >= 8) {
+            emitByte(Prefix.REXB);
+            regEnc -= 8;
+        } else if (byteinst && regEnc >= 4) {
+            emitByte(Prefix.REX);
+        }
+        return regEnc;
+    }
+
+    int prefixqAndEncode(int regEnc) {
+        if (regEnc < 8) {
+            emitByte(Prefix.REXW);
+        } else {
+            emitByte(Prefix.REXWB);
+            regEnc -= 8;
+        }
+        return regEnc;
+    }
+
+    int prefixAndEncode(int dstEnc, int srcEnc) {
+        return prefixAndEncode(dstEnc, srcEnc, false);
+    }
+
+    int prefixAndEncode(int dstEnc, int srcEnc, boolean byteinst) {
+        if (dstEnc < 8) {
+            if (srcEnc >= 8) {
+                emitByte(Prefix.REXB);
+                srcEnc -= 8;
+            } else if (byteinst && srcEnc >= 4) {
+                emitByte(Prefix.REX);
+            }
+        } else {
+            if (srcEnc < 8) {
+                emitByte(Prefix.REXR);
+            } else {
+                emitByte(Prefix.REXRB);
+                srcEnc -= 8;
+            }
+            dstEnc -= 8;
+        }
+        return dstEnc << 3 | srcEnc;
+    }
+
+    /**
+     * Creates prefix and the encoding of the lower 6 bits of the ModRM-Byte. It emits an operand prefix. If the given
+     * operands exceed 3 bits, the 4th bit is encoded in the prefix.
+     *
+     * @param regEnc the encoding of the register part of the ModRM-Byte
+     * @param rmEnc the encoding of the r/m part of the ModRM-Byte
+     * @return the lower 6 bits of the ModRM-Byte that should be emitted
+     */
+    private int prefixqAndEncode(int regEnc, int rmEnc) {
+        if (regEnc < 8) {
+            if (rmEnc < 8) {
+                emitByte(Prefix.REXW);
+            } else {
+                emitByte(Prefix.REXWB);
+                rmEnc -= 8;
+            }
+        } else {
+            if (rmEnc < 8) {
+                emitByte(Prefix.REXWR);
+            } else {
+                emitByte(Prefix.REXWRB);
+                rmEnc -= 8;
+            }
+            regEnc -= 8;
+        }
+        return regEnc << 3 | rmEnc;
+    }
+
+    private void prefix(CiRegister reg) {
+        if (reg.encoding >= 8) {
+            emitByte(Prefix.REXB);
+        }
+    }
+
+    private void prefix(CiAddress adr) {
+        if (adr.base().encoding >= MinEncodingNeedsRex) {
+            if (adr.index().encoding >= MinEncodingNeedsRex) {
+                emitByte(Prefix.REXXB);
+            } else {
+                emitByte(Prefix.REXB);
+            }
+        } else {
+            if (adr.index().encoding >= MinEncodingNeedsRex) {
+                emitByte(Prefix.REXX);
+            }
+        }
+    }
+
+    private void prefixq(CiAddress adr) {
+        if (adr.base().encoding >= MinEncodingNeedsRex) {
+            if (adr.index().encoding >= MinEncodingNeedsRex) {
+                emitByte(Prefix.REXWXB);
+            } else {
+                emitByte(Prefix.REXWB);
+            }
+        } else {
+            if (adr.index().encoding >= MinEncodingNeedsRex) {
+                emitByte(Prefix.REXWX);
+            } else {
+                emitByte(Prefix.REXW);
+            }
+        }
+    }
+
+    private void prefix(CiAddress adr, CiRegister reg) {
+        if (reg.encoding < 8) {
+            if (adr.base().encoding >= MinEncodingNeedsRex) {
+                if (adr.index().encoding >= MinEncodingNeedsRex) {
+                    emitByte(Prefix.REXXB);
+                } else {
+                    emitByte(Prefix.REXB);
+                }
+            } else {
+                if (adr.index().encoding >= MinEncodingNeedsRex) {
+                    emitByte(Prefix.REXX);
+                } else if (reg.encoding >= 4) {
+                    emitByte(Prefix.REX);
+                }
+            }
+        } else {
+            if (adr.base().encoding >= MinEncodingNeedsRex) {
+                if (adr.index().encoding >= MinEncodingNeedsRex) {
+                    emitByte(Prefix.REXRXB);
+                } else {
+                    emitByte(Prefix.REXRB);
+                }
+            } else {
+                if (adr.index().encoding >= MinEncodingNeedsRex) {
+                    emitByte(Prefix.REXRX);
+                } else {
+                    emitByte(Prefix.REXR);
+                }
+            }
+        }
+    }
+
+    private void prefixq(CiAddress adr, CiRegister src) {
+        if (src.encoding < 8) {
+            if (adr.base().encoding >= MinEncodingNeedsRex) {
+                if (adr.index().encoding >= MinEncodingNeedsRex) {
+                    emitByte(Prefix.REXWXB);
+                } else {
+                    emitByte(Prefix.REXWB);
+                }
+            } else {
+                if (adr.index().encoding >= MinEncodingNeedsRex) {
+                    emitByte(Prefix.REXWX);
+                } else {
+                    emitByte(Prefix.REXW);
+                }
+            }
+        } else {
+            if (adr.base().encoding >= MinEncodingNeedsRex) {
+                if (adr.index().encoding >= MinEncodingNeedsRex) {
+                    emitByte(Prefix.REXWRXB);
+                } else {
+                    emitByte(Prefix.REXWRB);
+                }
+            } else {
+                if (adr.index().encoding >= MinEncodingNeedsRex) {
+                    emitByte(Prefix.REXWRX);
+                } else {
+                    emitByte(Prefix.REXWR);
+                }
+            }
+        }
+    }
+
+    public final void addq(CiAddress dst, int imm32) {
+        prefixq(dst);
+        emitArithOperand(0x81, rax, dst, imm32);
+    }
+
+    public final void addq(CiAddress dst, CiRegister src) {
+        prefixq(dst, src);
+        emitByte(0x01);
+        emitOperandHelper(src, dst);
+    }
+
+    public final void addq(CiRegister dst, int imm32) {
+        prefixqAndEncode(dst.encoding);
+        emitArith(0x81, 0xC0, dst, imm32);
+    }
+
+    public final void addq(CiRegister dst, CiAddress src) {
+        prefixq(src, dst);
+        emitByte(0x03);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void addq(CiRegister dst, CiRegister src) {
+        prefixqAndEncode(dst.encoding, src.encoding);
+        emitArith(0x03, 0xC0, dst, src);
+    }
+
+    public final void andq(CiRegister dst, int imm32) {
+        prefixqAndEncode(dst.encoding);
+        emitArith(0x81, 0xE0, dst, imm32);
+    }
+
+    public final void andq(CiRegister dst, CiAddress src) {
+        prefixq(src, dst);
+        emitByte(0x23);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void andq(CiRegister dst, CiRegister src) {
+        prefixqAndEncode(dst.encoding, src.encoding);
+        emitArith(0x23, 0xC0, dst, src);
+    }
+
+    public final void bswapq(CiRegister reg) {
+        int encode = prefixqAndEncode(reg.encoding);
+        emitByte(0x0F);
+        emitByte(0xC8 | encode);
+    }
+
+    public final void cdqq() {
+        emitByte(Prefix.REXW);
+        emitByte(0x99);
+    }
+
+    public final void cmovq(ConditionFlag cc, CiRegister dst, CiRegister src) {
+        int encode = prefixqAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0x40 | cc.value);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void cmovq(ConditionFlag cc, CiRegister dst, CiAddress src) {
+        prefixq(src, dst);
+        emitByte(0x0F);
+        emitByte(0x40 | cc.value);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void cmpq(CiAddress dst, int imm32) {
+        prefixq(dst);
+        emitByte(0x81);
+        emitOperandHelper(rdi, dst);
+        emitInt(imm32);
+    }
+
+    public final void cmpq(CiRegister dst, int imm32) {
+        prefixqAndEncode(dst.encoding);
+        emitArith(0x81, 0xF8, dst, imm32);
+    }
+
+    public final void cmpq(CiAddress dst, CiRegister src) {
+        prefixq(dst, src);
+        emitByte(0x3B);
+        emitOperandHelper(src, dst);
+    }
+
+    public final void cmpq(CiRegister dst, CiRegister src) {
+        prefixqAndEncode(dst.encoding, src.encoding);
+        emitArith(0x3B, 0xC0, dst, src);
+    }
+
+    public final void cmpq(CiRegister dst, CiAddress src) {
+        prefixq(src, dst);
+        emitByte(0x3B);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void cmpxchgq(CiRegister reg, CiAddress adr) {
+        prefixq(adr, reg);
+        emitByte(0x0F);
+        emitByte(0xB1);
+        emitOperandHelper(reg, adr);
+    }
+
+    public final void cvtsi2sdq(CiRegister dst, CiRegister src) {
+        assert dst.isFpu();
+        emitByte(0xF2);
+        int encode = prefixqAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0x2A);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void cvtsi2ssq(CiRegister dst, CiRegister src) {
+        assert dst.isFpu();
+        emitByte(0xF3);
+        int encode = prefixqAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0x2A);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void cvttsd2siq(CiRegister dst, CiRegister src) {
+        assert src.isFpu();
+        emitByte(0xF2);
+        int encode = prefixqAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0x2C);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void cvttss2siq(CiRegister dst, CiRegister src) {
+        assert src.isFpu();
+        emitByte(0xF3);
+        int encode = prefixqAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0x2C);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void decq(CiRegister dst) {
+        // Don't use it directly. Use Macrodecrementq() instead.
+        // Use two-byte form (one-byte from is a REX prefix in 64-bit mode)
+        int encode = prefixqAndEncode(dst.encoding);
+        emitByte(0xFF);
+        emitByte(0xC8 | encode);
+    }
+
+    public final void decq(CiAddress dst) {
+        // Don't use it directly. Use Macrodecrementq() instead.
+        prefixq(dst);
+        emitByte(0xFF);
+        emitOperandHelper(rcx, dst);
+    }
+
+    public final void divq(CiRegister src) {
+        int encode = prefixqAndEncode(src.encoding);
+        emitByte(0xF7);
+        emitByte(0xF0 | encode);
+    }
+
+    public final void idivq(CiRegister src) {
+        int encode = prefixqAndEncode(src.encoding);
+        emitByte(0xF7);
+        emitByte(0xF8 | encode);
+    }
+
+    public final void imulq(CiRegister dst, CiRegister src) {
+        int encode = prefixqAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0xAF);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void imulq(CiRegister dst, CiRegister src, int value) {
+        int encode = prefixqAndEncode(dst.encoding, src.encoding);
+        if (Util.isByte(value)) {
+            emitByte(0x6B);
+            emitByte(0xC0 | encode);
+            emitByte(value);
+        } else {
+            emitByte(0x69);
+            emitByte(0xC0 | encode);
+            emitInt(value);
+        }
+    }
+
+    public final void incq(CiRegister dst) {
+        // Don't use it directly. Use Macroincrementq() instead.
+        // Use two-byte form (one-byte from is a REX prefix in 64-bit mode)
+        int encode = prefixqAndEncode(dst.encoding);
+        emitByte(0xFF);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void incq(CiAddress dst) {
+        // Don't use it directly. Use Macroincrementq() instead.
+        prefixq(dst);
+        emitByte(0xFF);
+        emitOperandHelper(rax, dst);
+    }
+
+    public final void movq(CiRegister dst, long imm64) {
+        int encode = prefixqAndEncode(dst.encoding);
+        emitByte(0xB8 | encode);
+        emitLong(imm64);
+    }
+
+    public final void movdq(CiRegister dst, CiRegister src) {
+
+        // table D-1 says MMX/SSE2
+        emitByte(0x66);
+
+        if (dst.isFpu()) {
+            assert dst.isFpu();
+            int encode = prefixqAndEncode(dst.encoding, src.encoding);
+            emitByte(0x0F);
+            emitByte(0x6E);
+            emitByte(0xC0 | encode);
+        } else if (src.isFpu()) {
+
+            // swap src/dst to get correct prefix
+            int encode = prefixqAndEncode(src.encoding, dst.encoding);
+            emitByte(0x0F);
+            emitByte(0x7E);
+            emitByte(0xC0 | encode);
+        } else {
+            Util.shouldNotReachHere();
+        }
+    }
+
+    public final void movsbq(CiRegister dst, CiAddress src) {
+        prefixq(src, dst);
+        emitByte(0x0F);
+        emitByte(0xBE);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void movsbq(CiRegister dst, CiRegister src) {
+        int encode = prefixqAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0xBE);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void movslq(CiRegister dst, int imm32) {
+        // dbx shows movslq(X86.rcx, 3) as movq $0x0000000049000000,(%X86.rbx)
+        // and movslq(X86.r8, 3); as movl $0x0000000048000000,(%X86.rbx)
+        // as a result we shouldn't use until tested at runtime...
+        Util.shouldNotReachHere();
+
+        int encode = prefixqAndEncode(dst.encoding);
+        emitByte(0xC7 | encode);
+        emitInt(imm32);
+    }
+
+    public final void movslq(CiAddress dst, int imm32) {
+        prefixq(dst);
+        emitByte(0xC7);
+        emitOperandHelper(rax, dst);
+        emitInt(imm32);
+    }
+
+    public final void movslq(CiRegister dst, CiAddress src) {
+        prefixq(src, dst);
+        emitByte(0x63);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void movslq(CiRegister dst, CiRegister src) {
+        int encode = prefixqAndEncode(dst.encoding, src.encoding);
+        emitByte(0x63);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void movswq(CiRegister dst, CiAddress src) {
+        prefixq(src, dst);
+        emitByte(0x0F);
+        emitByte(0xBF);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void movswq(CiRegister dst, CiRegister src) {
+        int encode = prefixqAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0xBF);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void movzbq(CiRegister dst, CiAddress src) {
+        prefixq(src, dst);
+        emitByte(0x0F);
+        emitByte(0xB6);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void movzbq(CiRegister dst, CiRegister src) {
+        int encode = prefixqAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0xB6);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void movzwq(CiRegister dst, CiAddress src) {
+        prefixq(src, dst);
+        emitByte(0x0F);
+        emitByte(0xB7);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void movzwq(CiRegister dst, CiRegister src) {
+        int encode = prefixqAndEncode(dst.encoding, src.encoding);
+        emitByte(0x0F);
+        emitByte(0xB7);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void negq(CiRegister dst) {
+        int encode = prefixqAndEncode(dst.encoding);
+        emitByte(0xF7);
+        emitByte(0xD8 | encode);
+    }
+
+    public final void notq(CiRegister dst) {
+        int encode = prefixqAndEncode(dst.encoding);
+        emitByte(0xF7);
+        emitByte(0xD0 | encode);
+    }
+
+    public final void orq(CiAddress dst, int imm32) {
+        prefixq(dst);
+        emitByte(0x81);
+        emitOperandHelper(rcx, dst);
+        emitInt(imm32);
+    }
+
+    public final void orq(CiRegister dst, int imm32) {
+        prefixqAndEncode(dst.encoding);
+        emitArith(0x81, 0xC8, dst, imm32);
+    }
+
+    public final void orq(CiRegister dst, CiAddress src) {
+        prefixq(src, dst);
+        emitByte(0x0B);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void orq(CiRegister dst, CiRegister src) {
+        prefixqAndEncode(dst.encoding, src.encoding);
+        emitArith(0x0B, 0xC0, dst, src);
+    }
+
+    public final void popq(CiAddress dst) {
+        prefixq(dst);
+        emitByte(0x8F);
+        emitOperandHelper(rax, dst);
+    }
+
+    public final void pushq(CiAddress src) {
+        prefixq(src);
+        emitByte(0xFF);
+        emitOperandHelper(rsi, src);
+    }
+
+    public final void rclq(CiRegister dst, int imm8) {
+        assert Util.isShiftCount(imm8 >> 1) : "illegal shift count";
+        int encode = prefixqAndEncode(dst.encoding);
+        if (imm8 == 1) {
+            emitByte(0xD1);
+            emitByte(0xD0 | encode);
+        } else {
+            emitByte(0xC1);
+            emitByte(0xD0 | encode);
+            emitByte(imm8);
+        }
+    }
+
+    public final void sarq(CiRegister dst, int imm8) {
+        assert Util.isShiftCount(imm8 >> 1) : "illegal shift count";
+        int encode = prefixqAndEncode(dst.encoding);
+        if (imm8 == 1) {
+            emitByte(0xD1);
+            emitByte(0xF8 | encode);
+        } else {
+            emitByte(0xC1);
+            emitByte(0xF8 | encode);
+            emitByte(imm8);
+        }
+    }
+
+    public final void sarq(CiRegister dst) {
+        int encode = prefixqAndEncode(dst.encoding);
+        emitByte(0xD3);
+        emitByte(0xF8 | encode);
+    }
+
+    public final void shlq(CiRegister dst, int imm8) {
+        assert Util.isShiftCount(imm8 >> 1) : "illegal shift count";
+        int encode = prefixqAndEncode(dst.encoding);
+        if (imm8 == 1) {
+            emitByte(0xD1);
+            emitByte(0xE0 | encode);
+        } else {
+            emitByte(0xC1);
+            emitByte(0xE0 | encode);
+            emitByte(imm8);
+        }
+    }
+
+    public final void shlq(CiRegister dst) {
+        int encode = prefixqAndEncode(dst.encoding);
+        emitByte(0xD3);
+        emitByte(0xE0 | encode);
+    }
+
+    public final void shrq(CiRegister dst, int imm8) {
+        assert Util.isShiftCount(imm8 >> 1) : "illegal shift count";
+        int encode = prefixqAndEncode(dst.encoding);
+        emitByte(0xC1);
+        emitByte(0xE8 | encode);
+        emitByte(imm8);
+    }
+
+    public final void shrq(CiRegister dst) {
+        int encode = prefixqAndEncode(dst.encoding);
+        emitByte(0xD3);
+        emitByte(0xE8 | encode);
+    }
+
+    public final void sqrtsd(CiRegister dst, CiAddress src) {
+        assert dst.isFpu();
+
+        emitByte(0xF2);
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0x51);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void subq(CiAddress dst, int imm32) {
+        prefixq(dst);
+        if (Util.isByte(imm32)) {
+            emitByte(0x83);
+            emitOperandHelper(rbp, dst);
+            emitByte(imm32 & 0xFF);
+        } else {
+            emitByte(0x81);
+            emitOperandHelper(rbp, dst);
+            emitInt(imm32);
+        }
+    }
+
+    public final void subq(CiRegister dst, int imm32) {
+        prefixqAndEncode(dst.encoding);
+        emitArith(0x81, 0xE8, dst, imm32);
+    }
+
+    public final void subq(CiAddress dst, CiRegister src) {
+        prefixq(dst, src);
+        emitByte(0x29);
+        emitOperandHelper(src, dst);
+    }
+
+    public final void subq(CiRegister dst, CiAddress src) {
+        prefixq(src, dst);
+        emitByte(0x2B);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void subq(CiRegister dst, CiRegister src) {
+        prefixqAndEncode(dst.encoding, src.encoding);
+        emitArith(0x2B, 0xC0, dst, src);
+    }
+
+    public final void testq(CiRegister dst, int imm32) {
+        // not using emitArith because test
+        // doesn't support sign-extension of
+        // 8bit operands
+        int encode = dst.encoding;
+        if (encode == 0) {
+            emitByte(Prefix.REXW);
+            emitByte(0xA9);
+        } else {
+            encode = prefixqAndEncode(encode);
+            emitByte(0xF7);
+            emitByte(0xC0 | encode);
+        }
+        emitInt(imm32);
+    }
+
+    public final void testq(CiRegister dst, CiRegister src) {
+        prefixqAndEncode(dst.encoding, src.encoding);
+        emitArith(0x85, 0xC0, dst, src);
+    }
+
+    public final void xaddq(CiAddress dst, CiRegister src) {
+        prefixq(dst, src);
+        emitByte(0x0F);
+        emitByte(0xC1);
+        emitOperandHelper(src, dst);
+    }
+
+    public final void xchgq(CiRegister dst, CiAddress src) {
+        prefixq(src, dst);
+        emitByte(0x87);
+        emitOperandHelper(dst, src);
+    }
+
+    public final void xchgq(CiRegister dst, CiRegister src) {
+        int encode = prefixqAndEncode(dst.encoding, src.encoding);
+        emitByte(0x87);
+        emitByte(0xc0 | encode);
+    }
+
+    public final void xorq(CiRegister dst, CiRegister src) {
+        prefixqAndEncode(dst.encoding, src.encoding);
+        emitArith(0x33, 0xC0, dst, src);
+    }
+
+    public final void xorq(CiRegister dst, CiAddress src) {
+
+        prefixq(src, dst);
+        emitByte(0x33);
+        emitOperandHelper(dst, src);
+
+    }
+
+    public final void membar(int barriers) {
+        if (target.isMP) {
+            // We only have to handle StoreLoad
+            if ((barriers & STORE_LOAD) != 0) {
+                // All usable chips support "locked" instructions which suffice
+                // as barriers, and are much faster than the alternative of
+                // using cpuid instruction. We use here a locked add [rsp],0.
+                // This is conveniently otherwise a no-op except for blowing
+                // flags.
+                // Any change to this code may need to revisit other places in
+                // the code where this idiom is used, in particular the
+                // orderAccess code.
+                lock();
+                addl(new CiAddress(CiKind.Word, RSP, 0), 0); // Assert the lock# signal here
+            }
+        }
+    }
+
+    @Override
+    public final void patchJumpTarget(int branch, int branchTarget) {
+        int op = codeBuffer.getByte(branch);
+        assert op == 0xE8 // call
+            || op == 0x00 // jump table entry
+            || op == 0xE9 // jmp
+            || op == 0xEB // short jmp
+            || (op & 0xF0) == 0x70 // short jcc
+            || op == 0x0F && (codeBuffer.getByte(branch + 1) & 0xF0) == 0x80 // jcc
+        : "Invalid opcode at patch point branch=" + branch + ", branchTarget=" + branchTarget + ", op=" + op;
+
+        if (op == 0x00) {
+            int offsetToJumpTableBase = codeBuffer.getShort(branch + 1);
+            int jumpTableBase = branch - offsetToJumpTableBase;
+            int imm32 = branchTarget - jumpTableBase;
+            codeBuffer.emitInt(imm32, branch);
+        } else if (op == 0xEB || (op & 0xF0) == 0x70) {
+
+            // short offset operators (jmp and jcc)
+            int imm8 = branchTarget - (branch + 2);
+            codeBuffer.emitByte(imm8, branch + 1);
+
+        } else {
+
+            int off = 1;
+            if (op == 0x0F) {
+                off = 2;
+            }
+
+            int imm32 = branchTarget - (branch + 4 + off);
+            codeBuffer.emitInt(imm32, branch + off);
+        }
+    }
+
+    @Override
+    public void nullCheck(CiRegister r) {
+        testl(AMD64.rax, new CiAddress(CiKind.Word, r.asValue(Word), 0));
+    }
+
+    @Override
+    public void align(int modulus) {
+        if (codeBuffer.position() % modulus != 0) {
+            nop(modulus - (codeBuffer.position() % modulus));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/target/amd64/AMD64Backend.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,84 @@
+/*
+ * 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.sun.c1x.target.amd64;
+
+import static com.sun.c1x.C1XCompilation.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.asm.*;
+import com.sun.c1x.gen.*;
+import com.sun.c1x.globalstub.*;
+import com.sun.c1x.lir.*;
+import com.sun.c1x.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(C1XCompiler 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(C1XCompilation 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(C1XCompilation 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.WithCompiler(compiler, 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/Compiler/src/com/sun/c1x/target/amd64/AMD64GlobalStubEmitter.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,436 @@
+/*
+ * 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.sun.c1x.target.amd64;
+
+import static com.sun.cri.ci.CiCallingConvention.Type.*;
+
+import java.util.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.asm.*;
+import com.sun.c1x.globalstub.*;
+import com.sun.c1x.target.amd64.AMD64Assembler.ConditionFlag;
+import com.sun.cri.ci.*;
+import com.sun.cri.ci.CiRegister.RegisterFlag;
+import com.sun.cri.ri.*;
+import com.sun.cri.xir.*;
+import com.sun.cri.xir.CiXirAssembler.XirConstant;
+import com.sun.cri.xir.CiXirAssembler.XirConstantOperand;
+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;
+
+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 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 C1XCompiler compiler;
+    private CiRegister[] registersSaved;
+
+    private boolean savedAllRegisters;
+
+    public AMD64GlobalStubEmitter(C1XCompiler compiler) {
+        this.compiler = compiler;
+        this.target = compiler.target;
+        this.runtime = compiler.runtime;
+    }
+
+    private void reset(CiKind resultKind, CiKind[] argTypes) {
+        asm = new AMD64MacroAssembler.WithCompiler(compiler, compiler.globalStubRegisterConfig);
+        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 = asm.finishTargetMethod(name, runtime, registerRestoreEpilogueOffset, true);
+        Object stubObject = runtime.registerGlobalStub(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 = asm.finishTargetMethod(name, runtime, registerRestoreEpilogueOffset, true);
+        Object stubObject = runtime.registerGlobalStub(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) {
+        C1XCompilation compilation = new C1XCompilation(compiler, null, -1, null);
+        try {
+            return emit(template, compilation);
+        } finally {
+            compilation.close();
+        }
+    }
+
+    public GlobalStub emit(XirTemplate template, C1XCompilation compilation) {
+        reset(template.resultOperand.kind, getArgumentKinds(template));
+        compilation.initFrameMap(0);
+        compilation.frameMap().setFrameSize(frameSize());
+        AMD64LIRAssembler assembler = new AMD64LIRAssembler(compilation);
+        asm = assembler.masm;
+
+        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 = asm.finishTargetMethod(template.name, runtime, registerRestoreEpilogueOffset, true);
+        Object stubObject = runtime.registerGlobalStub(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, asm.recordDataReferenceInCode(CiConstant.forLong(DoubleSignFlip)));
+        asm.xorpd(negateArgument, negateTemp);
+        negateEpilogue();
+    }
+
+    private void emitFNEG() {
+        negatePrologue();
+        asm.movsd(negateTemp, asm.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, asm.recordDataReferenceInCode(CiConstant.DOUBLE_0));
+        } else {
+            asm.ucomiss(convertArgument, asm.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++;
+        }
+
+        asm.setFrameSize(frameSize());
+        this.savedAllRegisters = false;
+    }
+
+    private void completeSavePrologue() {
+        CiCalleeSaveArea csa = compiler.globalStubRegisterConfig.getCalleeSaveArea();
+        this.saveSize = csa.size;
+        int entryCodeOffset = runtime.codeOffset();
+        if (entryCodeOffset != 0) {
+            // align to code size
+            asm.nop(entryCodeOffset);
+        }
+        asm.subq(AMD64.rsp, frameSize());
+        asm.setFrameSize(frameSize());
+        int frameToCSA = 0;
+        asm.save(csa, frameToCSA);
+        this.savedAllRegisters = true;
+    }
+
+    private void epilogue() {
+        assert registerRestoreEpilogueOffset == -1;
+        registerRestoreEpilogueOffset = asm.codeBuffer.position();
+
+        if (savedAllRegisters) {
+            CiCalleeSaveArea csa = compiler.globalStubRegisterConfig.getCalleeSaveArea();
+            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);
+        for (int i = 0; i < cc.locations.length; ++i) {
+            CiValue location = cc.locations[i];
+            loadArgument(i, location.asRegister());
+        }
+
+        // Call to the runtime
+        asm.directCall(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/Compiler/src/com/sun/c1x/target/amd64/AMD64LIRAssembler.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,2066 @@
+/*
+ * 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.sun.c1x.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.sun.c1x.*;
+import com.sun.c1x.asm.*;
+import com.sun.c1x.debug.*;
+import com.sun.c1x.gen.LIRGenerator.DeoptimizationStub;
+import com.sun.c1x.ir.*;
+import com.sun.c1x.lir.FrameMap.StackBlock;
+import com.sun.c1x.lir.*;
+import com.sun.c1x.target.amd64.AMD64Assembler.ConditionFlag;
+import com.sun.c1x.util.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ci.CiAddress.Scale;
+import com.sun.cri.ci.CiTargetMethod.JumpTable;
+import com.sun.cri.ci.CiTargetMethod.Mark;
+import com.sun.cri.xir.*;
+import com.sun.cri.xir.CiXirAssembler.RuntimeCallInformation;
+import com.sun.cri.xir.CiXirAssembler.XirInstruction;
+import com.sun.cri.xir.CiXirAssembler.XirLabel;
+import com.sun.cri.xir.CiXirAssembler.XirMark;
+
+/**
+ * This class implements the x86-specific code generation for LIR.
+ *
+ * @author Thomas Wuerthinger
+ * @author Ben L. Titzer
+ */
+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(C1XCompilation compilation) {
+        super(compilation);
+        masm = (AMD64MacroAssembler) compilation.masm();
+        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 void emitOsrEntry() {
+        throw Util.unimplemented();
+    }
+
+    @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 emitHere(CiValue dst, LIRDebugInfo info, boolean infoOnly) {
+        masm.recordSafepoint(codePos(), info);
+        if (!infoOnly) {
+            masm.codeBuffer.mark();
+            masm.leaq(dst.asRegister(), new CiAddress(CiKind.Word, InstructionRelative.asValue(), 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 emitPause() {
+        masm.pause();
+    }
+
+    @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) {
+            masm.recordDataReferenceInCode(constant);
+            masm.movq(dst, 0xDEADDEADDEADDEADL);
+        } else {
+            masm.movq(dst, masm.recordDataReferenceInCode(constant));
+        }
+    }
+
+    @Override
+    public void emitTraps() {
+        for (int i = 0; i < C1XOptions.MethodEndBreakpointGuards; ++i) {
+            masm.int3();
+        }
+    }
+
+    private void const2reg(CiRegister dst, float constant) {
+        if (constant == 0.0f) {
+            masm.xorps(dst, dst);
+        } else {
+            masm.movflt(dst, masm.recordDataReferenceInCode(CiConstant.forFloat(constant)));
+        }
+    }
+
+    private void const2reg(CiRegister dst, double constant) {
+        if (constant == 0.0f) {
+            masm.xorpd(dst, dst);
+        } else {
+            masm.movdbl(dst, masm.recordDataReferenceInCode(CiConstant.forDouble(constant)));
+        }
+    }
+
+    @Override
+    protected void const2reg(CiValue src, CiValue dest, LIRDebugInfo info) {
+        assert src.isConstant();
+        assert dest.isRegister();
+        CiConstant c = (CiConstant) src;
+
+        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();
+        }
+    }
+
+    @Override
+    protected void const2stack(CiValue src, CiValue dst) {
+        assert src.isConstant();
+        assert dst.isStackSlot();
+        CiStackSlot slot = (CiStackSlot) dst;
+        CiConstant c = (CiConstant) src;
+
+        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  : masm.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);
+        }
+    }
+
+    @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();
+        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  : masm.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();
+        }
+
+        if (info != null) {
+            asm.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));
+
+        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();
+        }
+    }
+
+    @Override
+    protected void reg2mem(CiValue src, CiValue dest, CiKind kind, LIRDebugInfo info, boolean unaligned) {
+        CiAddress toAddr = (CiAddress) dest;
+
+        if (info != null) {
+            asm.recordImplicitException(codePos(), info);
+        }
+
+        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();
+        }
+    }
+
+    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));
+
+        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();
+        }
+    }
+
+    @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) {
+            asm.recordImplicitException(codePos(), info);
+        }
+
+        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();
+        }
+    }
+
+    @Override
+    protected void emitReadPrefetch(CiValue src) {
+        CiAddress addr = (CiAddress) src;
+        switch (C1XOptions.ReadPrefetchInstr) {
+            case 0  : masm.prefetchnta(addr); break;
+            case 1  : masm.prefetcht0(addr); break;
+            case 2  : masm.prefetcht2(addr); break;
+            default : throw Util.shouldNotReachHere();
+        }
+    }
+
+    @Override
+    protected void emitOp3(LIROp3 op) {
+        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();
+        }
+    }
+
+    private boolean assertEmitBranch(LIRBranch op) {
+        assert op.block() == null || op.block().label() == op.label() : "wrong label";
+        if (op.block() != null) {
+            branchTargetBlocks.add(op.block());
+        }
+        if (op.unorderedBlock() != null) {
+            branchTargetBlocks.add(op.unorderedBlock());
+        }
+        return true;
+    }
+
+    private boolean assertEmitTableSwitch(LIRTableSwitch op) {
+        assert op.defaultTarget != null;
+        branchTargetBlocks.add(op.defaultTarget);
+        for (BlockBegin target : op.targets) {
+            assert target != null;
+            branchTargetBlocks.add(target);
+        }
+        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.mark();
+        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.mark();
+        masm.leaq(rscratch1, new CiAddress(CiKind.Word, InstructionRelative.asValue(), jumpTablePos - leaPos));
+        buf.setPosition(jumpTablePos);
+
+        // Emit jump table entries
+        for (BlockBegin 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);
+        masm.targetMethod.addAnnotation(jt);
+    }
+
+    @Override
+    protected void emitBranch(LIRBranch op) {
+
+        assert assertEmitBranch(op);
+
+        if (op.cond() == Condition.TRUE) {
+            if (op.info != null) {
+                asm.recordImplicitException(codePos(), op.info);
+            }
+            masm.jmp(op.label());
+        } else {
+            ConditionFlag acond = ConditionFlag.zero;
+            if (op.code == LIROpcode.CondFloatBranch) {
+                assert op.unorderedBlock() != null : "must have unordered successor";
+                masm.jcc(ConditionFlag.parity, op.unorderedBlock().label());
+                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;
+                    default : throw Util.shouldNotReachHere();
+                }
+            }
+            masm.jcc(acond, (op.label()));
+        }
+    }
+
+    @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);
+                masm.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);
+                masm.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);
+                masm.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);
+                masm.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;
+
+        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 = masm.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 = masm.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 (Util.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();
+                }
+            }
+        }
+    }
+
+    @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), masm.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();
+        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);
+        }
+    }
+
+    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 (C1XOptions.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);
+
+            asm.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 (C1XOptions.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);
+
+        asm.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);
+
+        asm.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) {
+        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, masm.recordDataReferenceInCode(CiConstant.forFloat(((CiConstant) opr2).asFloat()))); break;
+                    case Double  : masm.ucomisd(reg1, masm.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  :  {
+                        masm.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 Util.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();
+            }
+
+        } else {
+            throw Util.shouldNotReachHere(opr1.toString() + " opr2 = " + opr2);
+        }
+    }
+
+    @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 {
+                throw Util.unimplemented("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 (C1XOptions.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);
+        }
+        masm.indirectCall(reg, target, info);
+    }
+
+    @Override
+    protected void emitDirectCall(Object target, LIRDebugInfo info) {
+        masm.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);
+        }
+        masm.nativeCall(reg, symbol, info);
+    }
+
+    @Override
+    protected void emitTemplateCall(CiValue address) {
+        if (address == null) {
+            masm.directCall(null, null);
+            return;
+        }
+
+        CiRegister reg = rscratch1;
+        if (address.isRegister()) {
+            reg = address.asRegister();
+        } else {
+            moveOp(address, reg.asValue(address.kind), address.kind, null, false);
+        }
+        masm.indirectCall(reg, null, null);
+    }
+
+    @Override
+    protected void emitThrow(CiValue exceptionPC, CiValue exceptionOop, LIRDebugInfo info, boolean unwind) {
+       // exception object is not added to oop map by LinearScan
+       // (LinearScan assumes that no oops are in fixed registers)
+       // info.addRegisterOop(exceptionOop);
+        masm.directCall(unwind ? CiRuntimeCall.UnwindException : CiRuntimeCall.HandleException, info);
+        // enough room for two byte trap
+        masm.nop();
+    }
+
+    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";
+
+            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();
+            }
+        }
+    }
+
+    @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);
+            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();
+            }
+        }
+    }
+
+    @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));
+            }
+            masm.callGlobalStub(op.globalStub, null, asXmmFloatReg(dest), dest);
+
+        } else if (dest.kind.isDouble()) {
+            if (asXmmDoubleReg(left) != asXmmDoubleReg(dest)) {
+                masm.movdbl(asXmmDoubleReg(dest), asXmmDoubleReg(left));
+            }
+
+            masm.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 emitVolatileMove(CiValue src, CiValue dest, CiKind kind, LIRDebugInfo info) {
+        assert kind == CiKind.Long : "only for volatile long fields";
+
+        if (info != null) {
+            asm.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[] labels = new Label[snippet.template.labels.length];
+        for (int i = 0; i < labels.length; i++) {
+            labels[i] = new Label();
+        }
+        emitXirInstructions(instruction, snippet.template.fastPath, labels, instruction.getOperands(), snippet.marks);
+        if (snippet.template.slowPath != null) {
+            addSlowPath(new SlowPath(instruction, labels, snippet.marks));
+        }
+    }
+
+    @Override
+    protected void emitSlowPath(SlowPath sp) {
+        int start = -1;
+        if (C1XOptions.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 (C1XOptions.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) {
+                        asm.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) {
+                        asm.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) {
+                        asm.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];
+                    }
+                    masm.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;
+                    masm.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 {
+                        masm.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.";
+                    asm.recordSafepoint(codePos(), info);
+                    break;
+                }
+                case NullCheck: {
+                    asm.recordImplicitException(codePos(), info);
+                    CiValue pointer = operands[inst.x().index];
+                    asm.nullCheck(pointer.asRegister());
+                    break;
+                }
+                case Align: {
+                    asm.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 + C1XOptions.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 (C1XOptions.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);
+                        }
+                    }
+                    CiCalleeSaveArea csa = compilation.registerConfig.getCalleeSaveArea();
+                    if (csa.size != 0) {
+                        int frameToCSA = frameMap.offsetToCalleeSaveAreaStart();
+                        assert frameToCSA >= 0;
+                        masm.save(csa, frameToCSA);
+                    }
+                    break;
+                }
+                case PopFrame: {
+                    int frameSize = initialFrameSizeInBytes();
+
+                    CiCalleeSaveArea csa = compilation.registerConfig.getCalleeSaveArea();
+                    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 = asm.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.emitByte(b & 0xff);
+                    }
+                    break;
+                }
+                case ShouldNotReachHere: {
+                    if (inst.extra == null) {
+                        masm.stop("should not reach here");
+                    } else {
+                        masm.stop("should not reach here: " + inst.extra);
+                    }
+                    break;
+                }
+                default:
+                    throw Util.unimplemented("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);
+        masm.directCall(CiRuntimeCall.Deoptimize, stub.info);
+        masm.shouldNotReachHere();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/target/amd64/AMD64LIRGenerator.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,746 @@
+/*
+ * 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.sun.c1x.target.amd64;
+
+import static com.sun.cri.bytecode.Bytecodes.UnsignedComparisons.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.alloc.OperandPool.VariableFlag;
+import com.sun.c1x.gen.*;
+import com.sun.c1x.globalstub.*;
+import com.sun.c1x.ir.*;
+import com.sun.c1x.lir.*;
+import com.sun.c1x.util.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+/**
+ * This class implements the X86-specific portion of the LIR generator.
+ *
+ * @author Thomas Wuerthinger
+ * @author Ben L. Titzer
+ */
+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(C1XCompilation compilation) {
+        super(compilation);
+    }
+
+    @Override
+    protected CiValue exceptionPcOpr() {
+        return ILLEGAL;
+    }
+
+    @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() && Util.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 visitNegateOp(NegateOp 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);
+    }
+
+    @Override
+    public void visitSignificantBit(SignificantBitOp x) {
+        LIRItem value = new LIRItem(x.value(), this);
+        value.setDestroysRegister();
+        value.loadItem();
+        CiValue reg = createResultVariable(x);
+        if (x.op == Bytecodes.LSB) {
+            lir.lsb(value.result(), reg);
+        } else {
+            lir.msb(value.result(), reg);
+        }
+    }
+
+    public boolean livesLonger(Value x, Value y) {
+        BlockBegin bx = x.block();
+        BlockBegin by = y.block();
+        if (bx == null || by == null) {
+            return false;
+        }
+        return bx.loopDepth() < by.loopDepth();
+    }
+
+    public void visitArithmeticOpFloat(ArithmeticOp 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(ArithmeticOp x) {
+        int opcode = x.opcode;
+        if (opcode == Bytecodes.LDIV || opcode == Bytecodes.LREM) {
+            // emit inline 64-bit code
+            LIRDebugInfo info = x.needsZeroCheck() ? stateFor(x) : null;
+            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(), null);
+            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(), null);
+        }
+    }
+
+    public void visitArithmeticOpInt(ArithmeticOp 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 = x.needsZeroCheck() ? stateFor(x) : null;
+
+            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(ArithmeticOp 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 = x.needsZeroCheck() ? stateFor(x) : null;
+                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(), null);
+            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(), null);
+        }
+    }
+
+    @Override
+    public void visitArithmeticOp(ArithmeticOp 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);
+        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 visitShiftOp(ShiftOp 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 visitLogicOp(LogicOp 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(Op2 x) {
+        // (tw) TODO: Check what this is for?
+    }
+
+    @Override
+    public void visitCompareOp(CompareOp 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);
+            int code = x.opcode;
+            lir.fcmp2int(left.result(), right.result(), reg, (code == Bytecodes.FCMPL || code == Bytecodes.DCMPL));
+        } else if (x.x().kind.isLong() || x.x().kind.isWord()) {
+            CiValue reg = createResultVariable(x);
+            lir.lcmp2int(left.result(), right.result(), reg);
+        } else {
+            Util.unimplemented();
+        }
+    }
+
+    @Override
+    public void visitUnsignedCompareOp(UnsignedCompareOp x) {
+        LIRItem left = new LIRItem(x.x(), this);
+        LIRItem right = new LIRItem(x.y(), this);
+        left.loadItem();
+        right.loadItem();
+        Condition condition = null;
+        switch (x.op) {
+            case BELOW_THAN  : condition = Condition.BT; break;
+            case ABOVE_THAN  : condition = Condition.AT; break;
+            case BELOW_EQUAL : condition = Condition.BE; break;
+            case ABOVE_EQUAL : condition = Condition.AE; break;
+            default:
+                Util.unimplemented();
+        }
+        CiValue result = createResultVariable(x);
+        lir.cmp(condition, left.result(), right.result());
+        lir.cmove(condition, CiConstant.INT_1, CiConstant.INT_0, result);
+    }
+
+    @Override
+    public void visitCompareAndSwap(CompareAndSwap x) {
+
+        // (tw) TODO: Factor out common code with genCompareAndSwap.
+
+        CiKind dataKind = x.dataKind;
+        CiValue tempPointer = load(x.pointer());
+        CiAddress addr = getAddressForPointerOp(x, dataKind, tempPointer);
+
+        CiValue expectedValue = force(x.expectedValue(), AMD64.rax.asValue(dataKind));
+        CiValue newValue = load(x.newValue());
+        assert Util.archKindsEqual(newValue.kind, dataKind) : "invalid type";
+
+        if (dataKind.isObject()) { // Write-barrier needed for Object fields.
+            // Do the pre-write barrier : if any.
+            preGCWriteBarrier(addr, false, null);
+        }
+
+        CiValue pointer = newVariable(CiKind.Word);
+        lir.lea(addr, pointer);
+        CiValue result = createResultVariable(x);
+        CiValue resultReg = AMD64.rax.asValue(dataKind);
+        if (dataKind.isObject()) {
+            lir.casObj(pointer, expectedValue, newValue);
+        } else if (dataKind.isInt()) {
+            lir.casInt(pointer, expectedValue, newValue);
+        } else {
+            assert dataKind.isLong() || dataKind.isWord();
+            lir.casLong(pointer, expectedValue, newValue);
+        }
+
+        lir.move(resultReg, result);
+
+        if (dataKind.isObject()) { // Write-barrier needed for Object fields.
+            // Seems to be precise
+            postGCWriteBarrier(pointer, newValue);
+        }
+    }
+
+    @Override
+    protected void genCompareAndSwap(Intrinsic x, CiKind kind) {
+        assert x.numberOfArguments() == 5 : "wrong number of arguments: " + x.numberOfArguments();
+        // Argument 0 is the receiver.
+        LIRItem obj = new LIRItem(x.argumentAt(1), this); // object
+        LIRItem offset = new LIRItem(x.argumentAt(2), this); // offset of field
+        LIRItem val = new LIRItem(x.argumentAt(4), this); // replace field with val if matches cmp
+
+        assert obj.instruction.kind.isObject() : "invalid type";
+
+        assert val.instruction.kind == kind : "invalid type";
+
+        // get address of field
+        obj.loadItem();
+        offset.loadNonconstant();
+        CiAddress addr;
+        if (offset.result().isConstant()) {
+            addr = new CiAddress(kind, obj.result(), (int) ((CiConstant) offset.result()).asLong());
+        } else {
+            addr = new CiAddress(kind, obj.result(), offset.result());
+        }
+
+        // Compare operand needs to be in RAX.
+        CiValue cmp = force(x.argumentAt(3), AMD64.rax.asValue(kind));
+        val.loadItem();
+
+        CiValue pointer = newVariable(CiKind.Word);
+        lir.lea(addr, pointer);
+
+        if (kind.isObject()) { // Write-barrier needed for Object fields.
+            // Do the pre-write barrier : if any.
+            preGCWriteBarrier(pointer, false, null);
+        }
+
+        if (kind.isObject()) {
+            lir.casObj(pointer, cmp, val.result());
+        } else if (kind.isInt()) {
+            lir.casInt(pointer, cmp, val.result());
+        } else if (kind.isLong()) {
+            lir.casLong(pointer, cmp, val.result());
+        } else {
+            Util.shouldNotReachHere();
+        }
+
+        // generate conditional move of boolean result
+        CiValue result = createResultVariable(x);
+        lir.cmove(Condition.EQ, CiConstant.INT_1, CiConstant.INT_0, result);
+        if (kind.isObject()) { // Write-barrier needed for Object fields.
+            // Seems to be precise
+            postGCWriteBarrier(pointer, val.result());
+        }
+    }
+
+    @Override
+    protected void genMathIntrinsic(Intrinsic x) {
+        assert x.numberOfArguments() == 1 : "wrong type";
+
+        CiValue calcInput = load(x.argumentAt(0));
+
+        switch (x.intrinsic()) {
+            case java_lang_Math$abs:
+                lir.abs(calcInput, createResultVariable(x), ILLEGAL);
+                break;
+            case java_lang_Math$sqrt:
+                lir.sqrt(calcInput, createResultVariable(x), ILLEGAL);
+                break;
+            case java_lang_Math$sin:
+                setResult(x, callRuntimeWithResult(CiRuntimeCall.ArithmeticSin, null, calcInput));
+                break;
+            case java_lang_Math$cos:
+                setResult(x, callRuntimeWithResult(CiRuntimeCall.ArithmeticCos, null, calcInput));
+                break;
+            case java_lang_Math$tan:
+                setResult(x, callRuntimeWithResult(CiRuntimeCall.ArithmeticTan, null, calcInput));
+                break;
+            case java_lang_Math$log:
+                setResult(x, callRuntimeWithResult(CiRuntimeCall.ArithmeticLog, null, calcInput));
+                break;
+            case java_lang_Math$log10:
+                setResult(x, callRuntimeWithResult(CiRuntimeCall.ArithmeticLog10, null, calcInput));
+                break;
+            default:
+                Util.shouldNotReachHere("Unknown math intrinsic");
+        }
+    }
+
+    @Override
+    public void visitConvert(Convert x) {
+        CiValue input = load(x.value());
+        CiVariable result = newVariable(x.kind);
+        // arguments of lirConvert
+        GlobalStub globalStub = null;
+        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;
+        }
+        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 visitBlockBegin(BlockBegin x) {
+        // nothing to do for now
+    }
+
+    @Override
+    public void visitIf(If x) {
+        CiKind kind = x.x().kind;
+
+        Condition cond = x.condition();
+
+        LIRItem xitem = new LIRItem(x.x(), this);
+        LIRItem yitem = new LIRItem(x.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();
+        }
+
+        // add safepoint before generating condition code so it can be recomputed
+        if (x.isSafepoint()) {
+            emitXir(xir.genSafepoint(site(x)), x, stateFor(x, x.stateAfter()), null, false);
+        }
+        setNoResult(x);
+
+        CiValue left = xin.result();
+        CiValue right = yin.result();
+        lir.cmp(cond, left, right);
+        moveToPhi(x.stateAfter());
+        if (x.x().kind.isFloat() || x.x().kind.isDouble()) {
+            lir.branch(cond, right.kind, x.trueSuccessor(), x.unorderedSuccessor());
+        } else {
+            lir.branch(cond, right.kind, x.trueSuccessor());
+        }
+        assert x.defaultSuccessor() == x.falseSuccessor() : "wrong destination above";
+        lir.jump(x.defaultSuccessor());
+    }
+
+    @Override
+    protected void genGetObjectUnsafe(CiValue dst, CiValue src, CiValue offset, CiKind kind, boolean isVolatile) {
+        if (isVolatile && kind == CiKind.Long) {
+            CiAddress addr = new CiAddress(CiKind.Double, src, offset);
+            CiValue tmp = newVariable(CiKind.Double);
+            lir.load(addr, tmp, null);
+            CiValue spill = operands.newVariable(CiKind.Long, VariableFlag.MustStartInMemory);
+            lir.move(tmp, spill);
+            lir.move(spill, dst);
+        } else {
+            CiAddress addr = new CiAddress(kind, src, offset);
+            lir.load(addr, dst, null);
+        }
+    }
+
+    @Override
+    protected void genPutObjectUnsafe(CiValue src, CiValue offset, CiValue data, CiKind kind, boolean isVolatile) {
+        if (isVolatile && kind == CiKind.Long) {
+            CiAddress addr = new CiAddress(CiKind.Double, src, offset);
+            CiValue tmp = newVariable(CiKind.Double);
+            CiValue spill = operands.newVariable(CiKind.Double, VariableFlag.MustStartInMemory);
+            lir.move(data, spill);
+            lir.move(spill, tmp);
+            lir.move(tmp, addr);
+        } else {
+            CiAddress addr = new CiAddress(kind, src, offset);
+            boolean isObj = (kind == CiKind.Jsr || kind == CiKind.Object);
+            if (isObj) {
+                // Do the pre-write barrier, if any.
+                preGCWriteBarrier(addr, false, null);
+                lir.move(data, addr);
+                assert src.isVariableOrRegister() : "must be register";
+                // Seems to be a precise address
+                postGCWriteBarrier(addr, data);
+            } else {
+                lir.move(data, addr);
+            }
+        }
+    }
+
+    @Override
+    protected CiValue osrBufferPointer() {
+        return Util.nonFatalUnimplemented(null);
+    }
+
+    @Override
+    public void visitBoundsCheck(BoundsCheck boundsCheck) {
+        Value x = boundsCheck.index();
+        Value y = boundsCheck.length();
+        CiValue left = load(x);
+        CiValue right = null;
+        if (y.isConstant()) {
+            right = makeOperand(y);
+        } else {
+            right = load(y);
+        }
+        lir.cmp(boundsCheck.condition.negate(), left, right);
+        emitGuard(boundsCheck);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/target/amd64/AMD64MacroAssembler.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,506 @@
+/*
+ * 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.sun.c1x.target.amd64;
+
+import com.sun.c1x.*;
+import com.sun.c1x.asm.*;
+import com.sun.c1x.globalstub.*;
+import com.sun.c1x.lir.*;
+import com.sun.c1x.util.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+import com.sun.cri.xir.*;
+
+/**
+ * This class implements the AMD64-specific portion of the macro assembler.
+ *
+ * @author Thomas Wuerthinger
+ * @author Ben L. Titzer
+ */
+public class AMD64MacroAssembler extends AMD64Assembler {
+
+    private final CiRegister rscratch1;
+
+    public static class WithCompiler extends AMD64MacroAssembler {
+
+        private final C1XCompiler compiler;
+
+        public WithCompiler(C1XCompiler compiler, RiRegisterConfig registerConfig) {
+            super(compiler.target, registerConfig);
+            this.compiler = compiler;
+        }
+
+        @Override
+        public GlobalStub lookupGlobalStub(XirTemplate template) {
+            return compiler.lookupGlobalStub(template);
+        }
+    }
+
+    public AMD64MacroAssembler(CiTarget target, RiRegisterConfig registerConfig) {
+        super(target, registerConfig);
+        this.rscratch1 = registerConfig.getScratchRegister();
+    }
+
+    /**
+     * Must be overridden if compiling code that makes calls to global stubs.
+     */
+    public GlobalStub lookupGlobalStub(XirTemplate template) {
+        throw new IllegalArgumentException("This assembler does not support compiling calls to global stubs");
+    }
+
+    public final int callGlobalStub(XirTemplate stub, LIRDebugInfo info, CiRegister result, CiValue... args) {
+        assert args.length == stub.parameters.length;
+        return callGlobalStubHelper(lookupGlobalStub(stub), stub.resultOperand.kind, info, result, args);
+    }
+
+    public final int callGlobalStub(GlobalStub stub, LIRDebugInfo info, CiRegister result, CiValue... args) {
+        assert args.length == stub.argOffsets.length;
+        return callGlobalStubHelper(stub, stub.resultKind, info, result, args);
+    }
+
+    private int callGlobalStubHelper(GlobalStub stub, CiKind resultKind, LIRDebugInfo info, CiRegister result, CiValue... args) {
+        for (int i = 0; i < args.length; i++) {
+            storeParameter(args[i], stub.argOffsets[i]);
+        }
+
+        int pos = directCall(stub.stubObject, info);
+
+        if (result != CiRegister.None) {
+            loadResult(result, stub.resultOffset, resultKind);
+        }
+
+        // Clear out parameters
+        if (C1XOptions.GenAssertionCode) {
+            for (int i = 0; i < args.length; i++) {
+                movptr(new CiAddress(CiKind.Word, AMD64.RSP, stub.argOffsets[i]), 0);
+            }
+        }
+        return pos;
+    }
+
+    private void loadResult(CiRegister r, int offset, CiKind kind) {
+        if (kind == CiKind.Int || kind == CiKind.Boolean) {
+            movl(r, new CiAddress(CiKind.Int, AMD64.RSP, offset));
+        } else if (kind == CiKind.Float) {
+            movss(r, new CiAddress(CiKind.Float, AMD64.RSP, offset));
+        } else if (kind == CiKind.Double) {
+            movsd(r, new CiAddress(CiKind.Double, AMD64.RSP, offset));
+        } else {
+            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 {
+                movptr(new CiAddress(CiKind.Word, AMD64.RSP, offset), c.asInt());
+            }
+        } else if (registerOrConstant.isRegister()) {
+            if (k.isFloat()) {
+                movss(new CiAddress(CiKind.Float, AMD64.RSP, offset), registerOrConstant.asRegister());
+            } else if (k.isDouble()) {
+                movsd(new CiAddress(CiKind.Double, AMD64.RSP, offset), registerOrConstant.asRegister());
+            } else {
+                movq(new CiAddress(CiKind.Word, AMD64.RSP, offset), registerOrConstant.asRegister());
+            }
+        } else {
+            Util.shouldNotReachHere();
+        }
+    }
+
+    void movoop(CiRegister dst, CiConstant obj) {
+        assert obj.kind == CiKind.Object;
+        if (obj.isNull()) {
+            xorq(dst, dst);
+        } else {
+            if (target.inlineObjects) {
+                recordDataReferenceInCode(obj);
+                movq(dst, 0xDEADDEADDEADDEADL);
+            } else {
+                movq(dst, recordDataReferenceInCode(obj));
+            }
+        }
+    }
+
+    void movoop(CiAddress dst, CiConstant obj) {
+        movoop(rscratch1, obj);
+        movq(dst, rscratch1);
+    }
+
+    void mov64(CiAddress dst, long src) {
+        movq(rscratch1, src);
+        movq(dst, rscratch1);
+    }
+
+    void pushptr(CiAddress src) {
+        pushq(src);
+    }
+
+    void popptr(CiAddress src) {
+        popq(src);
+    }
+
+    void xorptr(CiRegister dst, CiRegister src) {
+        xorq(dst, src);
+    }
+
+    void xorptr(CiRegister dst, CiAddress src) {
+        xorq(dst, src);
+    }
+
+    // 64 bit versions
+
+    int correctedIdivq(CiRegister reg) {
+        // Full implementation of Java ldiv and lrem; checks for special
+        // case as described in JVM spec. : p.243 & p.271. The function
+        // returns the (pc) offset of the idivl instruction - may be needed
+        // for implicit exceptions.
+        //
+        // normal case special case
+        //
+        // input : X86Register.rax: dividend minLong
+        // reg: divisor (may not be eax/edx) -1
+        //
+        // output: X86Register.rax: quotient (= X86Register.rax idiv reg) minLong
+        // X86Register.rdx: remainder (= X86Register.rax irem reg) 0
+        assert reg != AMD64.rax && reg != AMD64.rdx : "reg cannot be X86Register.rax or X86Register.rdx register";
+        final long minLong = 0x8000000000000000L;
+        Label normalCase = new Label();
+        Label specialCase = new Label();
+
+        // check for special case
+        cmpq(AMD64.rax, recordDataReferenceInCode(CiConstant.forLong(minLong)));
+        jcc(AMD64Assembler.ConditionFlag.notEqual, normalCase);
+        xorl(AMD64.rdx, AMD64.rdx); // prepare X86Register.rdx for possible special case (where
+        // remainder = 0)
+        cmpq(reg, -1);
+        jcc(AMD64Assembler.ConditionFlag.equal, specialCase);
+
+        // handle normal case
+        bind(normalCase);
+        cdqq();
+        int idivqOffset = codeBuffer.position();
+        idivq(reg);
+
+        // normal and special case exit
+        bind(specialCase);
+
+        return idivqOffset;
+    }
+
+    void decrementq(CiRegister reg, int value) {
+        if (value == Integer.MIN_VALUE) {
+            subq(reg, value);
+            return;
+        }
+        if (value < 0) {
+            incrementq(reg, -value);
+            return;
+        }
+        if (value == 0) {
+            return;
+        }
+        if (value == 1 && C1XOptions.UseIncDec) {
+            decq(reg);
+        } else {
+            subq(reg, value);
+        }
+    }
+
+    void incrementq(CiRegister reg, int value) {
+        if (value == Integer.MIN_VALUE) {
+            addq(reg, value);
+            return;
+        }
+        if (value < 0) {
+            decrementq(reg, -value);
+            return;
+        }
+        if (value == 0) {
+            return;
+        }
+        if (value == 1 && C1XOptions.UseIncDec) {
+            incq(reg);
+        } else {
+            addq(reg, value);
+        }
+    }
+
+    // These are mostly for initializing null
+    void movptr(CiAddress dst, int src) {
+        movslq(dst, src);
+    }
+
+    void stop(String msg) {
+        if (C1XOptions.GenAssertionCode) {
+            // TODO: pass a pointer to the message
+            directCall(CiRuntimeCall.Debug, null);
+            hlt();
+        }
+    }
+
+    public final void cmp32(CiRegister src1, int imm) {
+        cmpl(src1, imm);
+    }
+
+    public final void cmp32(CiRegister src1, CiAddress src2) {
+        cmpl(src1, src2);
+    }
+
+    void cmpsd2int(CiRegister opr1, CiRegister opr2, CiRegister dst, boolean unorderedIsLess) {
+        assert opr1.isFpu() && opr2.isFpu();
+        ucomisd(opr1, opr2);
+
+        Label l = new Label();
+        if (unorderedIsLess) {
+            movl(dst, -1);
+            jcc(AMD64Assembler.ConditionFlag.parity, l);
+            jcc(AMD64Assembler.ConditionFlag.below, l);
+            movl(dst, 0);
+            jcc(AMD64Assembler.ConditionFlag.equal, l);
+            incrementl(dst, 1);
+        } else { // unordered is greater
+            movl(dst, 1);
+            jcc(AMD64Assembler.ConditionFlag.parity, l);
+            jcc(AMD64Assembler.ConditionFlag.above, l);
+            movl(dst, 0);
+            jcc(AMD64Assembler.ConditionFlag.equal, l);
+            decrementl(dst, 1);
+        }
+        bind(l);
+    }
+
+    void cmpss2int(CiRegister opr1, CiRegister opr2, CiRegister dst, boolean unorderedIsLess) {
+        assert opr1.isFpu();
+        assert opr2.isFpu();
+        ucomiss(opr1, opr2);
+
+        Label l = new Label();
+        if (unorderedIsLess) {
+            movl(dst, -1);
+            jcc(AMD64Assembler.ConditionFlag.parity, l);
+            jcc(AMD64Assembler.ConditionFlag.below, l);
+            movl(dst, 0);
+            jcc(AMD64Assembler.ConditionFlag.equal, l);
+            incrementl(dst, 1);
+        } else { // unordered is greater
+            movl(dst, 1);
+            jcc(AMD64Assembler.ConditionFlag.parity, l);
+            jcc(AMD64Assembler.ConditionFlag.above, l);
+            movl(dst, 0);
+            jcc(AMD64Assembler.ConditionFlag.equal, l);
+            decrementl(dst, 1);
+        }
+        bind(l);
+    }
+
+    void cmpptr(CiRegister src1, CiRegister src2) {
+        cmpq(src1, src2);
+    }
+
+    void cmpptr(CiRegister src1, CiAddress src2) {
+        cmpq(src1, src2);
+    }
+
+    void cmpptr(CiRegister src1, int src2) {
+        cmpq(src1, src2);
+    }
+
+    void cmpptr(CiAddress src1, int src2) {
+        cmpq(src1, src2);
+    }
+
+    void decrementl(CiRegister reg, int value) {
+        if (value == Integer.MIN_VALUE) {
+            subl(reg, value);
+            return;
+        }
+        if (value < 0) {
+            incrementl(reg, -value);
+            return;
+        }
+        if (value == 0) {
+            return;
+        }
+        if (value == 1 && C1XOptions.UseIncDec) {
+            decl(reg);
+        } else {
+            subl(reg, value);
+        }
+    }
+
+    void decrementl(CiAddress dst, int value) {
+        if (value == Integer.MIN_VALUE) {
+            subl(dst, value);
+            return;
+        }
+        if (value < 0) {
+            incrementl(dst, -value);
+            return;
+        }
+        if (value == 0) {
+            return;
+        }
+        if (value == 1 && C1XOptions.UseIncDec) {
+            decl(dst);
+        } else {
+            subl(dst, value);
+        }
+    }
+
+    void incrementl(CiRegister reg, int value) {
+        if (value == Integer.MIN_VALUE) {
+            addl(reg, value);
+            return;
+        }
+        if (value < 0) {
+            decrementl(reg, -value);
+            return;
+        }
+        if (value == 0) {
+            return;
+        }
+        if (value == 1 && C1XOptions.UseIncDec) {
+            incl(reg);
+        } else {
+            addl(reg, value);
+        }
+    }
+
+    void incrementl(CiAddress dst, int value) {
+        if (value == Integer.MIN_VALUE) {
+            addl(dst, value);
+            return;
+        }
+        if (value < 0) {
+            decrementl(dst, -value);
+            return;
+        }
+        if (value == 0) {
+            return;
+        }
+        if (value == 1 && C1XOptions.UseIncDec) {
+            incl(dst);
+        } else {
+            addl(dst, value);
+        }
+    }
+
+    void signExtendByte(CiRegister reg) {
+        if (reg.isByte()) {
+            movsxb(reg, reg); // movsxb
+        } else {
+            shll(reg, 24);
+            sarl(reg, 24);
+        }
+    }
+
+    void signExtendShort(CiRegister reg) {
+        movsxw(reg, reg); // movsxw
+    }
+
+    // Support optimal SSE move instructions.
+    void movflt(CiRegister dst, CiRegister src) {
+        assert dst.isFpu() && src.isFpu();
+        if (C1XOptions.UseXmmRegToRegMoveAll) {
+            movaps(dst, src);
+        } else {
+            movss(dst, src);
+        }
+    }
+
+    void movflt(CiRegister dst, CiAddress src) {
+        assert dst.isFpu();
+        movss(dst, src);
+    }
+
+    void movflt(CiAddress dst, CiRegister src) {
+        assert src.isFpu();
+        movss(dst, src);
+    }
+
+    void movdbl(CiRegister dst, CiRegister src) {
+        assert dst.isFpu() && src.isFpu();
+        if (C1XOptions.UseXmmRegToRegMoveAll) {
+            movapd(dst, src);
+        } else {
+            movsd(dst, src);
+        }
+    }
+
+    void movdbl(CiRegister dst, CiAddress src) {
+        assert dst.isFpu();
+        if (C1XOptions.UseXmmLoadAndClearUpper) {
+            movsd(dst, src);
+        } else {
+            movlpd(dst, src);
+        }
+    }
+
+    void xchgptr(CiRegister src1, CiRegister src2) {
+        xchgq(src1, src2);
+    }
+
+    public void shouldNotReachHere() {
+        stop("should not reach here");
+    }
+
+    public void enter(short imm16, byte imm8) {
+        emitByte(0xC8);
+        // appended:
+        emitByte(imm16 & 0xff);
+        imm16 >>= 8;
+        emitByte(imm16 & 0xff);
+        emitByte(imm8);
+    }
+
+    /**
+     * Emit code to save a given set of callee save registers to the
+     * {@linkplain CiCalleeSaveArea CSA} within the frame.
+     * @param csa the description of the CSA
+     * @param frameToCSA offset from the frame pointer to the CSA
+     */
+    public void save(CiCalleeSaveArea csa, int frameToCSA) {
+        CiRegisterValue frame = frameRegister.asValue();
+        for (CiRegister r : csa.registers) {
+            int offset = csa.offsetOf(r);
+            movq(new CiAddress(CiKind.Word, frame, frameToCSA + offset), r);
+        }
+    }
+
+    public void restore(CiCalleeSaveArea csa, int frameToCSA) {
+        CiRegisterValue frame = frameRegister.asValue();
+        for (CiRegister r : csa.registers) {
+            int offset = csa.offsetOf(r);
+            movq(r, new CiAddress(CiKind.Word, frame, frameToCSA + offset));
+        }
+    }
+
+    public void int3() {
+        emitByte(0xCC);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/target/amd64/AMD64XirAssembler.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.target.amd64;
+
+import static com.sun.cri.xir.XirTemplate.GlobalFlags.*;
+
+import java.util.*;
+
+import com.sun.c1x.util.*;
+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:
+                    throw Util.unimplemented("XIR operation " + i.op);
+            }
+            if (!appended) {
+                currentList.add(i);
+            }
+        }
+        for (XirLabel label : labels) {
+            assert 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/Compiler/src/com/sun/c1x/target/sparc/SPARC.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,97 @@
+/*
+ * 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.sun.c1x.target.sparc;
+
+import static com.sun.cri.bytecode.Bytecodes.MemoryBarriers.*;
+import static com.sun.cri.ci.CiRegister.RegisterFlag.*;
+
+import com.sun.cri.ci.*;
+
+/**
+ * Represents the SPARC architecture.
+ *
+ * @author Thomas Wuerthinger
+ */
+public class SPARC extends CiArchitecture {
+
+    // General purpose CPU registers
+    public static final CiRegister g0 = new CiRegister(0,  0,  8, "g0", CPU);
+    public static final CiRegister g1 = new CiRegister(1,  1,  8, "g1", CPU);
+    public static final CiRegister g2 = new CiRegister(2,  2,  8, "g2", CPU);
+    public static final CiRegister g3 = new CiRegister(3,  3,  8, "g3", CPU);
+    public static final CiRegister g4 = new CiRegister(4,  4,  8, "g4", CPU);
+    public static final CiRegister g5 = new CiRegister(5,  5,  8, "g5", CPU);
+    public static final CiRegister g6 = new CiRegister(6,  6,  8, "g6", CPU);
+    public static final CiRegister g7 = new CiRegister(7,  7,  8, "g7", CPU);
+
+    public static final CiRegister o0 = new CiRegister(8,  8,  8, "o0", CPU);
+    public static final CiRegister o1 = new CiRegister(9,  9,  8, "o1", CPU);
+    public static final CiRegister o2 = new CiRegister(10, 10, 8, "o2", CPU);
+    public static final CiRegister o3 = new CiRegister(11, 11, 8, "o3", CPU);
+    public static final CiRegister o4 = new CiRegister(12, 12, 8, "o4", CPU);
+    public static final CiRegister o5 = new CiRegister(13, 13, 8, "o5", CPU);
+    public static final CiRegister o6 = new CiRegister(14, 14, 8, "o6", CPU);
+    public static final CiRegister o7 = new CiRegister(15, 15, 8, "o7", CPU);
+
+    public static final CiRegister l0 = new CiRegister(16, 16, 8, "l0", CPU);
+    public static final CiRegister l1 = new CiRegister(17, 17, 8, "l1", CPU);
+    public static final CiRegister l2 = new CiRegister(18, 18, 8, "l2", CPU);
+    public static final CiRegister l3 = new CiRegister(19, 19, 8, "l3", CPU);
+    public static final CiRegister l4 = new CiRegister(20, 20, 8, "l4", CPU);
+    public static final CiRegister l5 = new CiRegister(21, 21, 8, "l5", CPU);
+    public static final CiRegister l6 = new CiRegister(22, 22, 8, "l6", CPU);
+    public static final CiRegister l7 = new CiRegister(23, 23, 8, "l7", CPU);
+
+    public static final CiRegister i0 = new CiRegister(24, 24, 8, "i0", CPU);
+    public static final CiRegister i1 = new CiRegister(25, 25, 8, "i1", CPU);
+    public static final CiRegister i2 = new CiRegister(26, 26, 8, "i2", CPU);
+    public static final CiRegister i3 = new CiRegister(27, 27, 8, "i3", CPU);
+    public static final CiRegister i4 = new CiRegister(28, 28, 8, "i4", CPU);
+    public static final CiRegister i5 = new CiRegister(29, 29, 8, "i5", CPU);
+    public static final CiRegister i6 = new CiRegister(30, 30, 8, "i6", CPU);
+    public static final CiRegister i7 = new CiRegister(31, 31, 8, "i7", CPU);
+
+    public static final CiRegister[] cpuRegisters = {
+        g0, g1, g2, g3, g4, g5, g6, g7,
+        o0, o1, o2, o3, o4, o5, o6, o7,
+        l0, l1, l2, l3, l4, l5, l6, l7,
+        i0, i1, i2, i3, i4, i5, i6, i7
+    };
+
+    protected SPARC(int wordSize, CiRegister[] registers) {
+        super("SPARC",
+              wordSize,
+              ByteOrder.BigEndian,
+              registers,
+              LOAD_LOAD | LOAD_STORE | STORE_STORE,
+              0,
+              i7.encoding + 1,
+              0);
+    }
+
+    @Override
+    public boolean isSPARC() {
+        return true;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/util/ArrayMap.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.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/Compiler/src/com/sun/c1x/util/BitMap2D.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,101 @@
+/*
+ * 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.sun.c1x.util;
+
+import com.sun.cri.ci.*;
+
+/**
+ * This class implements a two-dimensional bitmap.
+ *
+ * @author Marcelo Cintra
+ * @author Thomas Wuerthinger
+ */
+public final class BitMap2D {
+
+    private CiBitMap map;
+    private final int bitsPerSlot;
+
+    private int bitIndex(int slotIndex, int bitWithinSlotIndex)  {
+      return slotIndex * bitsPerSlot + bitWithinSlotIndex;
+    }
+
+    private boolean verifyBitWithinSlotIndex(int index)  {
+      return index < bitsPerSlot;
+    }
+
+    public BitMap2D(int sizeInSlots, int bitsPerSlot) {
+        map = new CiBitMap(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;
+           }
+           CiBitMap newBitMap = new CiBitMap(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/Compiler/src/com/sun/c1x/util/BlockWorkList.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.util;
+
+import com.sun.c1x.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.sun.c1x.graph.ScopeData}, because this worklist uses
+ * an externally supplied number.
+ *
+ * @author Ben L. Titzer
+ */
+public class BlockWorkList {
+    BlockBegin[] 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(BlockBegin 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(BlockBegin 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 BlockBegin 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 BlockBegin[5];
+        workListNumbers = new int[5];
+    }
+
+    private void grow() {
+        int prevLength = workList.length;
+        BlockBegin[] nworkList = new BlockBegin[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/Compiler/src/com/sun/c1x/util/IntList.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.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/Compiler/src/com/sun/c1x/util/Util.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,440 @@
+/*
+ * 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.sun.c1x.util;
+
+import java.util.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.debug.*;
+import com.sun.c1x.ir.*;
+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 <T> T nonFatalUnimplemented(T val) {
+        if (C1XOptions.FatalUnimplemented) {
+            throw new Error("unimplemented");
+        }
+        return val;
+    }
+
+    public static void nonFatalUnimplemented() {
+        if (C1XOptions.FatalUnimplemented) {
+            throw new Error("unimplemented");
+        }
+    }
+
+    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 C1XCompilation#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 C1XCompilation#compilation()} compilation.
+     */
+    public static boolean archKindsEqual(CiKind k1, CiKind k2) {
+        C1XCompilation compilation = C1XCompilation.compilation();
+        assert compilation != null : "missing compilation context";
+        return compilation.archKindsEqual(k1, k2);
+    }
+
+    /**
+     * Translates a given kind to a {@linkplain C1XCompilation#archKind(CiKind) canonical architecture}
+     * kind in the context of the {@linkplain C1XCompilation#compilation() current} compilation.
+     */
+    public static CiKind archKind(CiKind kind) {
+        C1XCompilation compilation = C1XCompilation.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(Instruction x, Instruction 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();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/value/FrameState.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,652 @@
+/*
+ * 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.sun.c1x.value;
+
+import java.util.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.graph.*;
+import com.sun.c1x.ir.*;
+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.
+ *
+ * @author Ben L. Titzer
+ */
+public abstract class FrameState {
+
+    /**
+     * The operand stack and local variables.
+     * The local variables occupy the index range {@code [0 .. maxLocals)}.
+     * The operand stack occupies the index range {@code [maxLocals .. values.length)}.
+     * The top of the operand stack is at index {@code maxLocals + stackIndex}.
+     * This does not include the operand stack or local variables of parent frames.
+     *
+     * {@linkplain CiKind#isDoubleWord() Double-word} local variables and
+     * operand stack values occupy 2 slots in this array with the second slot
+     * being {@code null}.
+     */
+    protected final Value[] values;
+
+    /**
+     * The depth of the operand stack.
+     * The top of stack value is in {@code values[maxLocals + stackIndex]}.
+     */
+    protected int stackIndex;
+
+    /**
+     * The number of local variables.
+     */
+    protected final int maxLocals;
+
+    protected final IRScope scope;
+
+    /**
+     * The bytecode index to which this frame state applies. This will be {@code -1}
+     * iff this state is mutable.
+     */
+    public final int bci;
+
+    /**
+     * The list of locks held by this frame state.
+     * This does not include locks held by parent frames.
+     */
+    protected ArrayList<Value> locks;
+
+    /**
+     * The number of minimum stack slots required for doing IR wrangling during
+     * {@linkplain GraphBuilder bytecode parsing}. While this may hide stack
+     * overflow issues in the original bytecode, the assumption is that such
+     * issues must be caught by the verifier.
+     */
+    private static final int MINIMUM_STACK_SLOTS = 1;
+
+    /**
+     * Creates a {@code FrameState} for the given scope and maximum number of stack and local variables.
+     *
+     * @param irScope the inlining context of the method
+     * @param bci the bytecode index of the frame state
+     * @param maxLocals maximum number of locals
+     * @param maxStack maximum size of the stack
+     */
+    public FrameState(IRScope irScope, int bci, int maxLocals, int maxStack) {
+        this.scope = irScope;
+        this.bci = bci;
+        this.values = new Value[maxLocals + Math.max(maxStack, MINIMUM_STACK_SLOTS)];
+        this.maxLocals = maxLocals;
+        C1XMetrics.FrameStatesCreated++;
+        C1XMetrics.FrameStateValuesCreated += this.values.length;
+    }
+
+    /**
+     * Copies the contents of this frame state so that further updates to either stack aren't reflected in the other.
+     * @param bci the bytecode index of the copy
+     * @param withLocals indicates whether to copy the local state
+     * @param withStack indicates whether to copy the stack state
+     * @param withLocks indicates whether to copy the lock state
+     *
+     * @return a new frame state with the specified components
+     */
+    public MutableFrameState copy(int bci, boolean withLocals, boolean withStack, boolean withLocks) {
+        final MutableFrameState other = new MutableFrameState(scope, bci, localsSize(), maxStackSize());
+        if (withLocals && withStack) {
+            // fast path: use array copy
+            int valuesSize = valuesSize();
+            assert other.values.length >= valuesSize : "array size: " + other.values.length + ", valuesSize: " + valuesSize + ", maxStackSize: " + maxStackSize() + ", localsSize: " + localsSize();
+            assert values.length >= valuesSize : "array size: " + values.length + ", valuesSize: " + valuesSize + ", maxStackSize: " + maxStackSize() + ", localsSize: " + localsSize();
+            System.arraycopy(values, 0, other.values, 0, valuesSize);
+            other.stackIndex = stackIndex;
+        } else {
+            if (withLocals) {
+                other.replaceLocals(this);
+            }
+            if (withStack) {
+                other.replaceStack(this);
+            }
+        }
+        if (withLocks) {
+            other.replaceLocks(this);
+        }
+        return other;
+    }
+
+    /**
+     * Gets a mutable copy ({@link MutableFrameState}) of this frame state.
+     */
+    public MutableFrameState copy() {
+        return copy(bci, true, true, true);
+    }
+
+    /**
+     * Gets an immutable copy of this frame state but without the stack.
+     */
+    public FrameState immutableCopyWithEmptyStack() {
+        return copy(bci, true, false, true);
+    }
+
+    /**
+     * Gets an immutable copy of this frame state but without the frame info.
+     */
+    public FrameState immutableCopyCodePosOnly() {
+        return copy(bci, false, false, false);
+    }
+
+    public boolean isSameAcrossScopes(FrameState other) {
+        assert stackSize() == other.stackSize();
+        assert localsSize() == other.localsSize();
+        assert locksSize() == other.locksSize();
+        for (int i = 0; i < stackIndex; i++) {
+            Value x = stackAt(i);
+            Value y = other.stackAt(i);
+            if (x != y && typeMismatch(x, y)) {
+                return false;
+            }
+        }
+        if (locks != null) {
+            for (int i = 0; i < locks.size(); i++) {
+                if (lockAt(i) != other.lockAt(i)) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Returns the inlining context associated with this frame state.
+     *
+     * @return the inlining context
+     */
+    public IRScope scope() {
+        return scope;
+    }
+
+    /**
+     * Returns the size of the local variables.
+     *
+     * @return the size of the local variables
+     */
+    public int localsSize() {
+        return maxLocals;
+    }
+
+    /**
+     * Gets number of locks held by this frame state.
+     */
+    public int locksSize() {
+        return locks == null ? 0 : locks.size();
+    }
+
+    public int totalLocksSize() {
+        return locksSize() + ((callerState() == null) ? 0 : callerState().totalLocksSize());
+    }
+
+    /**
+     * Gets the current size (height) of the stack.
+     */
+    public int stackSize() {
+        return stackIndex;
+    }
+
+    /**
+     * Gets the maximum size (height) of the stack.
+]     */
+    public int maxStackSize() {
+        return values.length - maxLocals;
+    }
+
+    /**
+     * Checks whether the stack is empty.
+     *
+     * @return {@code true} the stack is currently empty
+     */
+    public boolean stackEmpty() {
+        return stackIndex == 0;
+    }
+
+    /**
+     * 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
+        values[i] = null;
+    }
+
+    /**
+     * 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) {
+        assert i < maxLocals : "local variable index out of range: " + i;
+        Value x = values[i];
+        if (x != null) {
+            if (x.isIllegal()) {
+                return null;
+            }
+            assert x.kind.isSingleWord() || values[i + 1] == null || values[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) {
+        assert i < maxLocals : "local variable index out of range: " + i;
+        invalidateLocal(i);
+        values[i] = x;
+        if (isDoubleWord(x)) {
+            // (tw) if this was a double word then kill i+1
+            values[i + 1] = null;
+        }
+        if (i > 0) {
+            // if there was a double word at i - 1, then kill it
+            Value p = values[i - 1];
+            if (isDoubleWord(p)) {
+                values[i - 1] = null;
+            }
+        }
+    }
+
+    /**
+     * 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) {
+        assert i < stackIndex;
+        return values[i + maxLocals];
+    }
+
+    /**
+     * 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) {
+        assert i < maxLocals : "local variable index out of range: " + i;
+        return values[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);
+    }
+
+    /**
+     * 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 void setupPhiForStack(BlockBegin block, int i) {
+        Value p = stackAt(i);
+        if (p != null) {
+            if (p instanceof Phi) {
+                Phi phi = (Phi) p;
+                if (phi.block() == block && phi.isOnStack() && phi.stackIndex() == i) {
+                    return;
+                }
+            }
+            values[maxLocals + i] = new Phi(p.kind, block, -i - 1);
+        }
+    }
+
+    /**
+     * 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 void setupPhiForLocal(BlockBegin block, int i) {
+        Value p = values[i];
+        if (p instanceof Phi) {
+            Phi phi = (Phi) p;
+            if (phi.block() == block && phi.isLocal() && phi.localIndex() == i) {
+                return;
+            }
+        }
+        storeLocal(i, new Phi(p.kind, block, i));
+    }
+
+    /**
+     * 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 final Value valueAt(int i) {
+        return values[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 final int valuesSize() {
+        return maxLocals + stackIndex;
+    }
+
+    public final int callerStackSize() {
+        FrameState callerState = scope().callerState;
+        return callerState == null ? 0 : callerState.stackSize();
+    }
+
+    public void checkPhis(BlockBegin block, FrameState other) {
+        checkSize(other);
+        final int max = valuesSize();
+        for (int i = 0; i < max; i++) {
+            Value x = values[i];
+            Value y = other.values[i];
+            if (x != null && x != y) {
+                if (x instanceof Phi) {
+                    Phi phi = (Phi) x;
+                    if (phi.block() == block) {
+                        for (int j = 0; j < phi.inputCount(); j++) {
+                            if (phi.inputIn(other) == null) {
+                                throw new CiBailout("phi " + phi + " has null operand at new predecessor");
+                            }
+                        }
+                        continue;
+                    }
+                }
+                throw new CiBailout("instruction is not a phi or null at " + i);
+            }
+        }
+    }
+
+    private void checkSize(FrameState other) {
+        if (other.stackIndex != stackIndex) {
+            throw new CiBailout("stack sizes do not match");
+        } else if (other.maxLocals != maxLocals) {
+            throw new CiBailout("local sizes do not match");
+        }
+    }
+
+    public void merge(BlockBegin block, FrameState other) {
+        checkSize(other);
+        for (int i = 0; i < valuesSize(); i++) {
+            Value x = values[i];
+            if (x != null) {
+                Value y = other.values[i];
+                if (x != y) {
+                    if (typeMismatch(x, y)) {
+                        if (x instanceof Phi) {
+                            Phi phi = (Phi) x;
+                            if (phi.block() == block) {
+                                phi.makeDead();
+                            }
+                        }
+                        values[i] = null;
+                        continue;
+                    }
+                    if (i < maxLocals) {
+                        // this a local
+                        setupPhiForLocal(block, i);
+                    } else {
+                        // this is a stack slot
+                        setupPhiForStack(block, i - maxLocals);
+                    }
+                }
+            }
+        }
+    }
+
+    private static boolean typeMismatch(Value x, Value y) {
+        return y == null || x.kind != y.kind;
+    }
+
+    private static boolean isDoubleWord(Value x) {
+        return x != null && x.kind.isDoubleWord();
+    }
+
+    /**
+     * The interface implemented by a client of {@link FrameState#forEachPhi(BlockBegin, PhiProcedure)} and
+     * {@link FrameState#forEachLivePhi(BlockBegin, PhiProcedure)}.
+     */
+    public static interface PhiProcedure {
+        boolean doPhi(Phi phi);
+    }
+
+    /**
+     * Traverses all {@linkplain Phi phis} of a given block in this frame state.
+     *
+     * @param block only phis {@linkplain Phi#block() associated} with this block are traversed
+     * @param proc the call back invoked for each live phi traversed
+     */
+    public boolean forEachPhi(BlockBegin block, PhiProcedure proc) {
+        int max = this.valuesSize();
+        for (int i = 0; i < max; i++) {
+            Value instr = values[i];
+            if (instr instanceof Phi && !instr.isDeadPhi()) {
+                Phi phi = (Phi) instr;
+                if (block == null || phi.block() == block) {
+                    if (!proc.doPhi(phi)) {
+                        return false;
+                    }
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Traverses all live {@linkplain Phi phis} of a given block in this frame state.
+     *
+     * @param block only phis {@linkplain Phi#block() associated} with this block are traversed
+     * @param proc the call back invoked for each live phi traversed
+     */
+    public final boolean forEachLivePhi(BlockBegin block, PhiProcedure proc) {
+        int max = this.valuesSize();
+        for (int i = 0; i < max; i++) {
+            Value instr = values[i];
+            if (instr instanceof Phi && instr.isLive() && !instr.isDeadPhi()) {
+                Phi phi = (Phi) instr;
+                if (block == null || phi.block() == block) {
+                    if (!proc.doPhi(phi)) {
+                        return false;
+                    }
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Checks whether this frame state has any {@linkplain Phi phi} statements.
+     */
+    public boolean hasPhis() {
+        int max = valuesSize();
+        for (int i = 0; i < max; i++) {
+            Value value = values[i];
+            if (value instanceof Phi) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Iterates over all the values in this frame state and its callers, including the stack, locals, and locks.
+     * @param closure the closure to apply to each value
+     */
+    public void valuesDo(ValueClosure closure) {
+        valuesDo(this, closure);
+    }
+
+    /**
+     * Iterates over all the values of a given frame state and its callers, including the stack, locals, and locks.
+     * @param closure the closure to apply to each value
+     */
+    public static void valuesDo(FrameState state, ValueClosure closure) {
+        do {
+            final int max = state.valuesSize();
+            for (int i = 0; i < max; i++) {
+                if (state.values[i] != null) {
+                    Value newValue = closure.apply(state.values[i]);
+                    state.values[i] = newValue;
+                }
+            }
+            if (state.locks != null) {
+                for (int i = 0; i < state.locks.size(); i++) {
+                    Value instr = state.locks.get(i);
+                    if (instr != null) {
+                        state.locks.set(i, closure.apply(instr));
+                    }
+                }
+            }
+            state = state.callerState();
+        } while (state != null);
+    }
+
+    /**
+     * 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 and it's callers.
+     *
+     * @param proc the call back called to process each live value traversed
+     */
+    public final void forEachLiveStateValue(ValueProcedure proc) {
+        FrameState state = this;
+        while (state != null) {
+            final int max = state.valuesSize();
+            for (int i = 0; i < max; i++) {
+                Value value = state.values[i];
+                if (value != null && value.isLive()) {
+                    proc.doValue(value);
+                }
+            }
+            state = state.callerState();
+        }
+    }
+
+    public static String toString(FrameState fs) {
+        StringBuilder sb = new StringBuilder();
+        String nl = String.format("%n");
+        while (fs != null) {
+            if (fs.scope == null) {
+                sb.append("<no method>").append(" [bci: ").append(fs.bci).append(']');
+                break;
+            } else {
+                CiUtil.appendLocation(sb, fs.scope.method, fs.bci).append(nl);
+                for (int i = 0; i < fs.localsSize(); ++i) {
+                    Value value = fs.localAt(i);
+                    sb.append(String.format("  local[%d] = %-8s : %s%n", i, value == null ? "bogus" : value.kind.javaName, value));
+                }
+                for (int i = 0; i < fs.stackSize(); ++i) {
+                    Value value = fs.stackAt(i);
+                    sb.append(String.format("  stack[%d] = %-8s : %s%n", i, value == null ? "bogus" : value.kind.javaName, value));
+                }
+                for (int i = 0; i < fs.locksSize(); ++i) {
+                    Value value = fs.lockAt(i);
+                    sb.append(String.format("  lock[%d] = %-8s : %s%n", i, value == null ? "bogus" : value.kind.javaName, value));
+                }
+                fs = fs.callerState();
+            }
+        }
+        return sb.toString();
+    }
+
+    @Override
+    public String toString() {
+        return toString(this);
+    }
+
+    public CiCodePos toCodePos() {
+        FrameState caller = callerState();
+        CiCodePos callerCodePos = null;
+        if (caller != null) {
+            callerCodePos = caller.toCodePos();
+        }
+        return new CiCodePos(callerCodePos, scope.method, bci);
+    }
+
+    /**
+     * Creates a new {@code MutableFrameState} corresponding to inlining the specified method into this point in this frame state.
+     * @param scope the IRScope representing the inlined method
+     * @return a new frame state representing the state at the beginning of inlining the specified method into this one
+     */
+    public MutableFrameState pushScope(IRScope scope) {
+        assert scope.caller == this.scope;
+        RiMethod method = scope.method;
+        return new MutableFrameState(scope, -1, method.maxLocals(), method.maxStackSize());
+    }
+
+    /**
+     * Creates a new {@code MutableFrameState} corresponding to the state upon returning from this inlined method into the outer
+     * IRScope.
+     * @return a new frame state representing the state at exit from this frame state
+     */
+    public MutableFrameState popScope() {
+        IRScope callingScope = scope.caller;
+        assert callingScope != null;
+        FrameState callerState = scope.callerState;
+        MutableFrameState res = new MutableFrameState(callingScope, bci, callerState.maxLocals, callerState.maxStackSize() + stackIndex);
+        System.arraycopy(callerState.values, 0, res.values, 0, callerState.values.length);
+        System.arraycopy(values, maxLocals, res.values, res.maxLocals + callerState.stackIndex, stackIndex);
+        res.stackIndex = callerState.stackIndex + stackIndex;
+        assert res.stackIndex >= 0;
+        res.replaceLocks(callerState);
+        return res;
+    }
+
+    /**
+     * Gets the caller frame state.
+     *
+     * @return the caller frame state or {@code null} if this is a top-level state
+     */
+    public FrameState callerState() {
+        return scope.callerState;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/value/MutableFrameState.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,366 @@
+/*
+ * 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.sun.c1x.value;
+
+import java.util.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.ir.*;
+import com.sun.c1x.util.*;
+import com.sun.cri.ci.*;
+
+
+/**
+ * The {@code MutableFrameState} class extends abstract {@link FrameState} with methods modifying the frame state.
+ * Only {@code MutableFrameState} can be instantiated and thus the object references in which it is stored decide
+ * whether it is used as immutable or not. Thus and because they can be shared at different places in the compiler,
+ * {@link FrameState}s must not be cast to {@code MutableFrameState}s. Instead, a new copy must be created using
+ * {@link FrameState#copy()}.
+ * Contrariwise and as an optimization, an instance referenced as {@code MutableFrameState} can be assigned to
+ * a variable, field, or method parameter of type {@link FrameState} without creating an immutable copy before
+ * (using {@link #immutableCopy(int)}) if the state is not mutated after the assignment.
+ *
+ * @author Michael Duller
+ */
+public final class MutableFrameState extends FrameState {
+
+    public MutableFrameState(IRScope irScope, int bci, int maxLocals, int maxStack) {
+        super(irScope, bci, maxLocals, maxStack);
+    }
+
+    /**
+     * Replace the local variables in this frame state with the local variables from the specified frame state. This is
+     * used in inlining.
+     *
+     * @param with the frame state containing the new local variables
+     */
+    public void replaceLocals(FrameState with) {
+        assert with.maxLocals == maxLocals;
+        System.arraycopy(with.values, 0, values, 0, maxLocals);
+    }
+
+    /**
+     * Replace the stack in this frame state with the stack from the specified frame state. This is used in inlining.
+     *
+     * @param with the frame state containing the new local variables
+     */
+    public void replaceStack(FrameState with) {
+        System.arraycopy(with.values, with.maxLocals, values, maxLocals, with.stackIndex);
+        stackIndex = with.stackIndex;
+        assert stackIndex >= 0;
+    }
+
+    /**
+     * Replace the locks in this frame state with the locks from the specified frame state. This is used in inlining.
+     *
+     * @param with the frame state containing the new local variables
+     */
+    public void replaceLocks(FrameState with) {
+        if (with.locks == null) {
+            locks = null;
+        } else {
+            locks = Util.uncheckedCast(with.locks.clone());
+        }
+    }
+
+    /**
+     * Clears all values on this stack.
+     */
+    public void clearStack() {
+        stackIndex = 0;
+    }
+
+    public void clearLocals() {
+        for (int i = 0; i < maxLocals; i++) {
+            values[i] = null;
+        }
+    }
+
+    /**
+     * Truncates this stack to the specified size.
+     * @param size the size to truncate to
+     */
+    public void truncateStack(int size) {
+        stackIndex = size;
+        assert stackIndex >= 0;
+    }
+
+    /**
+     * 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 stackIndex >= 0;
+        assert maxLocals + stackIndex < values.length;
+        values[maxLocals + 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);
+    }
+
+    /**
+     * 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) {
+        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() {
+        assert stackIndex >= 1;
+        return values[maxLocals + --stackIndex];
+    }
+
+    /**
+     * 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());
+    }
+
+    private static Value assertKind(CiKind kind, Value x) {
+        assert x != null && (x.kind == kind || !isTypesafe()) : "kind=" + kind + ", value=" + x + ((x == null) ? "" : ", value.kind=" + x.kind);
+        return x;
+    }
+
+    private static Value assertLong(Value x) {
+        assert x != null && (x.kind == CiKind.Long || !isTypesafe());
+        return x;
+    }
+
+    private static Value assertJsr(Value x) {
+        assert x != null && (x.kind == CiKind.Jsr || !isTypesafe());
+        return x;
+    }
+
+    private static Value assertInt(Value x) {
+        assert x != null && (x.kind == CiKind.Int || !isTypesafe());
+        return x;
+    }
+
+    private static Value assertFloat(Value x) {
+        assert x != null && (x.kind == CiKind.Float || !isTypesafe());
+        return x;
+    }
+
+    private static Value assertObject(Value x) {
+        assert x != null && (x.kind == CiKind.Object || !isTypesafe());
+        return x;
+    }
+
+    private static Value assertWord(Value x) {
+        assert x != null && (x.kind == CiKind.Word || !isTypesafe());
+        return x;
+    }
+
+    private static Value assertDouble(Value x) {
+        assert x != null && (x.kind == CiKind.Double || !isTypesafe());
+        return x;
+    }
+
+    /**
+     * 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];
+        int y = maxLocals + base;
+        for (int i = 0; i < size; ++i) {
+            assert values[y] != null || values[y - 1].kind.jvmSlots == 2;
+            r[i] = values[y++];
+        }
+        stackIndex = base;
+        assert stackIndex >= 0;
+        return r;
+    }
+
+    /**
+     * 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(IRScope scope, Value obj, int totalNumberOfLocks) {
+        if (locks == null) {
+            locks = new ArrayList<Value>(4);
+        }
+        locks.add(obj);
+        scope.updateMaxLocks(totalNumberOfLocks);
+    }
+
+    /**
+     * Unlock the lock on the top of the stack.
+     */
+    public void unlock() {
+        locks.remove(locks.size() - 1);
+    }
+
+    /**
+     * Gets an immutable copy of this state.
+     * @param bci the bytecode index of the new frame state
+     */
+    public FrameState immutableCopy(int bci) {
+        return copy(bci, true, true, true);
+    }
+
+    /**
+     * Determines if the current compilation is typesafe.
+     */
+    private static boolean isTypesafe() {
+        return C1XCompilation.compilation().isTypesafe();
+    }
+
+    private static void assertHigh(Value x) {
+        assert x == null;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/value/package-info.java	Wed Apr 27 11:43:22 2011 +0200
@@ -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.sun.c1x.value;